一、歸併排序描述
把長度爲n的輸入序列分成兩個長度爲n/2的子序列;
對這兩個子序列分別採用歸併排序;
將兩個排序好的子序列合併成一個最終的排序序列。
將兩個的有序數列合併成一個有序數列,我們稱之爲"歸併"。
歸併排序(Merge Sort)就是利用歸併思想對數列進行排序。根據具體的實現,歸併排序包括"從上往下"和"從下往上"2種方式。
-
1、從下往上的歸併排序:將待排序的數列分成若干個長度爲1的子數列,然後將這些數列兩兩合併;得到若干個長度爲2的有序數列,再將這些數列兩兩合併;得到若干個長度爲4的有序數列,再將它們兩兩合併;直接合併成一個數列爲止。這樣就得到了我們想要的排序結果。(參考下面的圖片)
-
2、從上往下的歸併排序:它與"從下往上"在排序上是反方向的。它基本包括3步:
- ① 分解:將當前區間一分爲二,即求分裂點 mid = (low + high)/2;
- ② 求解:遞歸地對兩個子區間a[low...mid] 和 a[mid+1...high]進行歸併排序。遞歸的終結條件是子區間長度爲1。
- ③ 合併:將已排序的兩個子區間a[low...mid]和 a[mid+1...high]歸併爲一個有序的區間a[low...high]。
三、代碼實現
public class MergeSort { public static void Sort(int[] arr,int left,int right,int[] temp) { if(left<right) { int mid = (left + right) / 2; Sort(arr, left, mid, temp); Sort(arr, mid + 1, right, temp); Merge(arr, left, mid, right, temp); } } /// <summary> /// 歸併 /// </summary> /// <param name="arr">原始數組</param> /// <param name="left">左邊有序序列初始索引</param> /// <param name="mid">中間索引</param> /// <param name="right">右邊有序序列初始索引</param> /// <param name="temp">中轉數組</param> private static void Merge(int[] arr, int left, int mid, int right, int[] temp) { int i = left; int j = mid + 1; int t = 0; while(i<=mid && j<=right) { //如果左邊的有序序列的當前元素小於等於右邊的有序序列的當前元素,則將左邊的當前元素拷貝到temp數組 if(arr[i]<=arr[j]) { temp[t] = arr[i]; t+=1; i+=1; } else { //否則,將右邊的當前元素拷貝到temp數組 temp[t] = arr[j]; t+=1; j+=1; } } //左邊有序序列剩餘的元素全部填充到temp while(i<=mid) { temp[t] = arr[i]; t+=1; i+=1; } //右邊的有序序列剩餘元素全部填充到temp while(j<=right) { temp[t] = arr[j]; t+=1; j+=1; } //將temp數組的元素拷貝到arr t = 0; int tempLeft = left; while(tempLeft <=right) { arr[tempLeft] = temp[t]; t+=1; tempLeft+=1; } } }