經典排序—歸並排序思想及實現


歸並排序(Merge)是將兩個(或兩個以上)有序表合並成一個新的有序表,即把待排序序列分為若干個子序列,每個子序列是有序的。然后再把有序子序列合並為整體有序序列。

歸並排序是建立在歸並操作上的一種有效的排序算法。該算法是采用分治法(Divide and Conquer)的一個非常典型的應用。 將已有序的子序列合並,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合並成一個有序表,稱為2-路歸並。歸並排序算法穩定,數組需要O(n)的額外空間,鏈表需要O(log(n))的額外空間,時間復雜度為O(nlog(n)),算法不是自適應的,不需要對數據的隨機讀取。

實現原理:

1、申請空間,使其大小為兩個已經排序序列之和,該空間用來存放合並后的序列;

2、設定兩個指針變量,最初位置分別指向兩個已經排好序的數組序列的起始位置;

3、比較兩個指針所指向的元素,選擇相對小的元素放入到申請的合並空間里,並移動此指針到下一位置;

4、繼續重復步驟3直到某一指針達到序列尾;

5、當一個指針到達一個序列尾時,將另一序列剩下的所有元素直接復制到合並序列尾。

代碼(Java):

public class MergeSort {

    public static void mergeSort(int[] data, int left, int right)

   {
          if (left >= right)
                    return ;
    // 找出中間索引
        int center = (left + right) / 2;
   // 對左邊數組進行遞歸
         mergeSort(data, left, center);
   // 對右邊數組進行遞歸
      mergeSort(data, center + 1, right);
   // 合並
      merge(data, left, center, right);

   }

   /**
    * 將兩個數組進行歸並,歸並前面2個數組已有序,歸並后依然有序
  *
  * @param data
  * 數組對象
  * @param left
  * 左數組的第一個元素的索引
  * @param center
  * 左數組的最后一個元素的索引,center+1是右數組第一個元素的索引
  * @param right
  * 右數組最后一個元素的索引
  */
  public static void merge(int[] data, int left, int center, int right) {
    // 申請臨時數組
    int[] tmpArr = new int[data.length];
  // 右數組第一個元素索引
    int mid = center + 1;
     // third 記錄臨時數組的索引
    int third = left;
 // 緩存左數組第一個元素的索引
    int tmp = left;
  while (left <= center && mid <= right) {
   // 從兩個數組中取出最小的放入臨時數組
   if (data[left] <= data[mid])

   {
      tmpArr[third++] = data[left++];

   } else

  {
      tmpArr[third++] = data[mid++];
   // count+=center-left+1;
  }
}
   // 剩余部分依次放入臨時數組(實際上兩個while只會執行其中一個)
     while (mid <= right) {
    tmpArr[third++] = data[mid++];
    }
  while (left <= center) {
    tmpArr[third++] = data[left++];
   }
   // 將臨時數組中的內容拷貝回原數組中
    // (原left-right范圍的內容被復制回原數組)
   while (tmp <= right)

       {
         data[tmp] = tmpArr[tmp++];
        }
    }
}

利用歸並排序的思想可以解決如數組逆序對的問題等等


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM