排序 - 歸併排序 [2]


我們知道歸併排序是拆分和合並兩部分。

說完了歸併排序的 拆分部分

繼續說說合並部分。

 

還是先回顧下拆分吧。

隨便說個數組 { 9, 2, 7, 1, 3, 6, 5, 4}

拆分過程:
   9,  2, 7, 1          3, 6, 5,4

 9, 2      7,1       3, 6     5, 4          

9  2     7   1       3   6     5   4 

 

好,到此我們對原數組完成了拆分,如果你不瞭解拆分,請一定看我的上一篇來弄懂拆分是如何工作的。

 

上面的拆分結果是最終的結果,其實合併是穿插在拆分過程中的。

 

當 9,2,7,1  --> 9,2 --> 9 & 2 的時候,9是某次遞歸中的左半部分,而2是這次遞歸中的右半部分。

當左半部分和右半部分都完成拆分的時候,我們就需要對他進行合併。

 

合併規則:

1. 創建一個數組,數組長度等於待合併左半部分和右半部分的數組元素總和;

2. 比較左面數組和右面數組中的第一個元素,選其較小者放入數組的第一個元素位置;

    2.5. 如果左面數組和右面數組都只有一個元素,那麼此時我們已經處理了其中一個,對上例來講,我們已經把 右面數組的唯一元素:2 放入了數組中,那麼就只剩下左面元素:9;再將9直接追加到新數組的後面即可;

3. 綜合2和2.5,我們知道合併是這樣進行的:總是選擇兩邊較小的元素追加到新元素的下一個元素的位置;

4. 當其中一部分(左面部分或右面部分)處理完成後,將另一部分的所有元素直接追加到新數組的後面,如此完成合並。

 

合併過程如下:

9  2    7   1     3  6     5  4

2,9     1,7        3,6      4,5

1,2,7,9            3,4,5,6

1,2,3,4,5,6,7,9

 

我在上一篇中提到一個問題:

拆分的結果就是每個元素都被拆分爲一個單元,那乾脆直接將每個元素都當做一個單元來處理不就得了,幹嘛還做什麼拆分?

原因在合併過程中就體現出來了。

 

1. 細心點,你會發現每次合併的左右兩半部分數組都是 有序 的,只有有序,才能用上面的合併的規則;

2. 拆分和合並是一個遞歸過程,遞歸,還是遞歸,還要花些時間理解。

 

這篇寫的不好。心不在焉。。如果你看到覺得不明白,歡迎討論。

package r;
 
public class MyMergeSort {
 
 public static int[] array = {19, 1,90, 22, 11, 12, 9, 3};
 
 public static void mergeSort(int[] sortArr, int start, int end) {
    int len = end - start;
    if (len < 1) return;
    else {
      int mid = start + len / 2;
      printArr(sortArr, start, mid);
      printArr(sortArr, mid + 1, end);
     
     System.out.println("======================");
      mergeSort(sortArr, start, mid);
      mergeSort(sortArr, mid + 1, end);
     
      merge(sortArr, start, mid, mid+1, end);
     
      System.out.println("*************PRINT *********");
      printArr(sortArr, start, end);
    }
 }
 
 private static void merge(int[] sortArr, int leftStart, int leftEnd, intrightStart, int rightEnd) {
    int leftPointer = leftStart;
    int rightPointer = rightStart;
   
    int[] sortedArr = new int[rightEnd -leftStart + 1];
    int index = -1;
    while (leftPointer <= leftEnd &&rightPointer <= rightEnd) {
      index++;
      int s = getSmaller(sortArr, leftPointer,rightPointer);
      sortedArr[index] = sortArr[s];
     
      if (s == leftPointer) leftPointer++;
      else rightPointer++;
    }
   
    if (leftPointer <= leftEnd) {
      for (int i = leftPointer; i <=leftEnd; i++) {
        sortedArr[++index] = sortArr[i];
      }
    }
   
    if (rightPointer <= rightEnd) {
      for (int i = rightPointer; i <=rightEnd; i++) {
        sortedArr[++index] = sortArr[i];
      }
   }
   
    // Copy back
    for (int i = 0; i < sortedArr.length;i++) {
      sortArr[leftStart + i] = sortedArr[i];
    }
 }
 
 private static int getSmaller(int[] sortArr, int leftPointer, intrightPointer) {
    if (sortArr[leftPointer] <sortArr[rightPointer])
      return leftPointer;
    else
      return rightPointer;
 }
 
 private  static voidprintArr(int[] arr, int start, int end) {
    for (int i = start; i <= end; i++) {
      System.out.print(arr[i] + "  ");
    }
    System.out.println("\r\n--------");
 }
 
 
 public static void main(String[] args) {
    mergeSort(array, 0, array.length - 1);
   
//    printArr(array, 0, array.length - 1);
 }
}


 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章