日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java 迭代实现归并排序

發布時間:2023/12/9 java 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java 迭代实现归并排序 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 歸并排序思想:
  • 歸并排序實現步驟
    • 1.數組拆分
    • 2.數組第一次合并
    • 3.數組循環合并
  • 迭代實現歸并排序完整代碼

歸并排序思想:

  • 大家都說將大問題化為小問題,這個是比較抽象的,其實如果小問題也不好解決,那我們化為小問題又有什么用呢
  • 舉個例子 [5, 2, 1, 4, 3] ,我們可以把它分為小數組,但小數組有多小呢,這就是看小問題好不好解決,如分為 [5, 2, 1][4,3] ,那第一個數組排序也至少需要比較兩次,那么這個小問題相對來說不是很好解決,如果看第二個數組,只需要比較一次就行了,可以發現如果一個數組有三個元素我們要比較兩次,一個數組有兩個元素我們只要比較一次就行了,很明顯小問題最好是分為兩個元素的數組
  • 分為小問題,解決了小問題又有什么用呢,如果給你兩個數組 [1, 5][3,4],因為兩個數組內部是有序的,合并這兩個數組是很簡單的,只需要維護兩個指針,每次只將兩個指針指向的最小值,放入一個新數組,就可以合并成功了,只需要比較3次我們就需要排序完成了,比較過程是先比較1和3,放入1到第三個數組,將第一個指針往后移動指向5,比較5和3,放入3,移動第二個指針,指向4,比較5和4,放入4,最后放入由于第二個數組已經空了,將第一個數組剩下元素放入第三個數組
  • 合并和分解有個類似的東西,我們分解考慮過分為兩個元素還是三個元素,合并的時候同樣有這個問題,我們是一次合并三個數組還是合并兩數組呢,和上面道理一樣,合并三個數組每選出一個元素都需要比較兩次,而合并兩個數組每選出一個元素只需要比較一次
  • 從上面可以看到歸并排序優化排序速度的方法有兩個,分為小數組后比較次數非常少,還有就是各個小數組之間內部有序后合并也很快,只有建立在這兩個的基礎上,將大問題分為小問題再合并才會快
  • 歸并排序實現步驟

    1.數組拆分

    我們的上面的思路是將數組拆成多個2個元素的數組,然后讓每個兩個元素數組都有序,但我們沒必要真正創建那么多個小數組,只要想象在一個數組中有很多分界線就行

    public static void mergeSortUp(int[] nums) {int stepLength = 2; for (int i = 0; i < nums.length; i += stepLength) {if (i + 1 < nums.length && nums[i] > nums[i + 1]) {tempValue = nums[i];nums[i] = nums[i+1];nums[i+1] = tempValue;}} }

    2.數組第一次合并

  • 可能看起來比較復雜,但只是因為我沒想出怎么優雅的防止數組越界
  • 第一個for循環為了將數組分區,我們一開始以2個元素為一個數組,那么我們先合并的時候,就先合并兩個數組,就是以4個元素為一個界限,所以for循環就是將數組進行分區
  • while循環是將兩個小數組合成一個數組,因為我們不能改變原數組nums,則只能將元素全放到temp數組中
  • 兩個數組合并為一個數組需要考慮三種情況,也就是兩個數組都有元素沒放到第三個數組上,左邊的數組有元素沒放到第三個數組上和右邊的數組有元素沒放到第三個數組,分為這三種情況合并就行了
  • 合并完成后我們就完成了第一次合并,將我們分的小數組個數減少了一半,下一步就是繼續合并,直至只剩一個數組
  • public static void mergeSortUp(int[] nums) {for (int i = 0; i < nums.length; i += stepLength * 2) {int index = i, left = i, right = i + stepLength;while (left < i + stepLength || (right < i + stepLength * 2 && right < nums.length)) {if (left < i + stepLength && (right < i + stepLength * 2 && right < nums.length)) {if (nums[left] < nums[right]) {temp[index] = nums[left];left++;} else {temp[index] = nums[right];right++;}} else if (left < i + stepLength && left < nums.length) {temp[index] = nums[left];left++;} else if (right < i + stepLength * 2 && right < nums.length){temp[index] = nums[right];right++;} else {break;}index++;}} }

    3.數組循環合并

  • 可以看出在第二步變化上并不大,我們只需要先交換nums和temp兩個數組的引用就行,因為nums是我們要的數組,而temp是排序的數組,在上一步合并后合并的數組是放在temp中的,所以我們要把temp給nums,而把nums給temp讓它繼續當中間數組,簡單來說就是原來的nums數組我們不要了,讓它當作中間容器
  • stepLength步長要翻倍,因為第二次我們要合并兩個4個元素數組為8個元素數組,但是我們最開始待排序的數組可能沒有8個,所以我們的while條件上是tempLength / 2 就是為了處理邊界情況
  • 我們可以理解當stepLength代表有序數組的長度,如果它大于原數組長度,說明原數組已經排序成功
  • while (stepLength / 2 < nums.length) {for (int i = 0; i < nums.length; i += stepLength * 2) {int index = i, left = i, right = i + stepLength;while (left < i + stepLength || (right < i + stepLength * 2 && right < nums.length)) {if (left < i + stepLength && (right < i + stepLength * 2 && right < nums.length)) {if (nums[left] < nums[right]) {temp[index] = nums[left];left++;} else {temp[index] = nums[right];right++;}} else if (left < i + stepLength && left < nums.length) {temp[index] = nums[left];left++;} else if (right < i + stepLength * 2 && right < nums.length){temp[index] = nums[right];right++;} else {break;}index++;}}t = nums;nums = temp;temp = t;stepLength *= 2; }

    迭代實現歸并排序完整代碼

    public class MergeSortUpDemo {public static void main(String[] args) {int[] nums = new int[]{5, 2, 1, 4, 3,2,5,6,1,2,5};int[] temp = new int[nums.length];mergeSortUp(nums);System.out.println(Arrays.toString(nums));}// temp為中間數組,長度和nums一樣的空數組public static void mergeSortUp(int[] nums) {int[] temp = new int[nums.length];int[] t;int stepLength = 2;int tempValue = 0;// 以2個元素為單位排序for (int i = 0; i < nums.length; i += stepLength) {if (i + 1 < nums.length && nums[i] > nums[i + 1]) {tempValue = nums[i];nums[i] = nums[i+1];nums[i+1] = tempValue;}}// 將相鄰的兩個塊合并while (stepLength / 2 < nums.length) {// i用來分區for (int i = 0; i < nums.length; i += stepLength * 2) {int index = i, left = i, right = i + stepLength;// 在區內才循環while (left < i + stepLength || (right < i + stepLength * 2 && right < nums.length)) {if (left < i + stepLength && (right < i + stepLength * 2 && right < nums.length)) {if (nums[left] < nums[right]) {temp[index] = nums[left];left++;} else {temp[index] = nums[right];right++;}} else if (left < i + stepLength && left < nums.length) {temp[index] = nums[left];left++;} else if (right < i + stepLength * 2 && right < nums.length){temp[index] = nums[right];right++;} else {break;}index++;}}// 合并一次后的數組為temp,將nums設為合并后的數組,然后在temp數組里面再次合并t = nums;nums = temp;temp = t;stepLength *= 2;}} }

    總結

    以上是生活随笔為你收集整理的Java 迭代实现归并排序的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。