1. 程式人生 > 其它 >歸併排序【Java】

歸併排序【Java】

 程式碼:

 1 public static void mergeSort(int[] arr) {
 2         if (arr == null || arr.length < 2) {
 3             return;
 4         }
 5         mergeSort(arr, 0, arr.length - 1);
 6     }
 7 
 8     public static void mergeSort(int[] arr, int l, int r) {
 9         if (l == r) {
10             return
; 11 } 12 int mid = l + ((r - l) >> 1); 13 mergeSort(arr, l, mid); //左側有序 14 mergeSort(arr, mid + 1, r); //右側有序 15 merge(arr, l, mid, r); //merge 16 } 17 18 public static void merge(int[] arr, int l, int m, int r) { 19 int[] help = new
int[r - l + 1]; 20 int i = 0; 21 int p1 = l; 22 int p2 = m + 1; 23 while (p1 <= m && p2 <= r) { 24 help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++]; //誰小拷貝誰(p1和p2都不越界) 25 } 26 while (p1 <= m) { 27 help[i++] = arr[p1++];
28 } 29 while (p2 <= r) { 30 help[i++] = arr[p2++]; 31 } 32 for (i = 0; i < help.length; i++) { 33 arr[l + i] = help[i]; 34 } 35 }

 

如果看程式碼的流程,歸併排序的是把一組資料,一分為二,之後對左邊的資料繼續一分為二,分到實在不能再分(也就是l == r的時候)

最後再排序!這其實是分而治之的思想,假設有5個數【2,4,9,6,3】我們直接排序不好排,但是如果我們分一下呢?

變成【2,4】和【9,6,3】如果對左邊再分一次呢?

【2】、【4】這時候2 和 4 都是單獨的一個數,我們顯然知道單獨的一個數是最好排序的,2 和4 本身就是有序的,因為它們只有自己!

對於左邊,當分到不能再分的時候return;,遞迴呼叫的“遞”的過程就完成了,接下來就是歸了。

在歸的過程中,會多次進入右側的遞迴函式,但是由於 l == r 所以實質上右側的呼叫是無效的,只需要呼叫merge函式完成左側單個數據

的依次排序!

當左側完成的時候,會進入最初始的那個 l 和 r 的值,接下來再次進入右側的遞迴函式,完成同樣的一個過程,最後左側資料和右側資料

都是各自有序的,當程式跳出(mergeSort(arr, mid + 1, r); //右側有序)這一行程式碼的時候,會執行最外層函式的最後一次merge,這時候

對所有資料完成最後一次排序引數應該是最初的引數,也就是 l = 0 ; mid = 2 ; r = 4 ! merge(0,2.4) 這時候所有資料就都是有序的了!

 

程式碼的執行順序?

當進入一條遞迴語句的時候,會多次迴圈整個過程,只有當滿足結束條件的時候,才會return!

但此時要注意,這時候return只是退出了這一條語句而已,對於最外層的函式來說,只是這一條

語句執行完畢了。還是需要繼續往下執行的,也就是會進入下一條遞迴語句,對於歸併排序來說

先進入左邊遞迴,左邊有序,之後進入右邊遞迴,右邊有序!最後進入最外層的函式執行最後一

條merge語句,把整個陣列完成排序!

下面是我畫的一個草圖:

 

 

 

該圖片來自:https://www.cnblogs.com/l199616j/p/10604351.html