【排序算法】歸併排序(C++實現)

COPY FROM:http://blog.csdn.net/left_la/article/details/8656953

歸併排序是利用"歸併"技術來進行排序。歸併是指將若干個已排序的子文件合併成一個有序的文件。常見的歸併排序有兩路歸併排序(Merge Sort),多相歸併排序(Polyphase Merge Sort),Strand排序(Strand Sort)。下面介紹第一種:

(一)兩路歸併排序

最差時間複雜度:O(nlogn)
平均時間複雜度:O(nlogn)
最差空間複雜度:O(n)
穩定性:穩定

兩路歸併排序(Merge Sort),也就是我們常說的歸併排序,也叫合併排序。它是建立在歸併操作上的一種有效的排序算法,歸併操作即將兩個已經排序的序列合併成一個序列的操作。該算法是採用分治法(Divide and Conquer)的一個非常典型的應用。
歸併操作的基本步驟如下:
1.申請兩個與已經排序序列相同大小的空間,並將兩個序列拷貝其中;
2.設定最初位置分別爲兩個已經拷貝排序序列的起始位置,比較兩個序列元素的大小,依次選擇相對小的元素放到原始序列;
3.重複2直到某一拷貝序列全部放入原始序列,將另一個序列剩下的所有元素直接複製到原始序列尾。

設歸併排序的當前區間是R[low..high],分治法的三個步驟是:
1.分解:將當前區間一分爲二,即求分裂點
2.求解:遞歸地對兩個子區間R[low..mid]和R[mid+1..high]進行歸併排序;
3.組合:將已排序的兩個子區間R[low..mid]和R[mid+1..high]歸併爲一個有序的區間R[low..high]。
遞歸的終結條件:子區間長度爲1(一個記錄自然有序)。

算法示意圖:


代碼實現:

  1. void Merge(int *a, int p, int q, int r)  
  2. {  
  3.     int n1 = q-p+1;  
  4.     int n2 = r-q;  
  5.     int *L = new int[n1+1];  
  6.     int *R = new int[n2+1];  
  7.     int i, j, k;  
  8.       
  9.     for (i=0; i<n1; i++){  
  10.         L[i] = a[p+i];  
  11.     }  
  12.     for (j=0; j<n2; j++){  
  13.         R[j] = a[q+j+1];  
  14.     }  
  15.     L[n1] = 10000000;  
  16.     R[n2] = 10000000;  
  17.   
  18.     for (i=0, j=0, k=p; k<=r; k++)  
  19.     {  
  20.         if (L[i]<=R[j])  
  21.         {  
  22.             a[k] = L[i];  
  23.             i++;  
  24.         }else{  
  25.             a[k] = R[j];  
  26.             j++;  
  27.         }  
  28.     }  
  29.   
  30.     delete []L;  
  31.     delete []R;  
  32. }  
  33.   
  34. void MergeSort1(int *a, int p, int r)  
  35. {  
  36.     if (p<r)  
  37.     {  
  38.         int q = (p+r)/2;  
  39.         MergeSort1(a, p, q);  
  40.         MergeSort1(a, q+1, r);  
  41.         Merge(a, p, q, r);  
  42.     }  
  43. }  

雖然插入排序的時間複雜度爲O(n^2),歸併排序的時間複雜度爲O(nlogn),但插入排序中的常數因子使得它在n較小時,運行得要更快一些。因此,在歸併排序算法中,當子問題足夠小時,採用插入排序算法就比較合適了。

代碼實現:

  1. void MergeSort2(int *a, int p, int r)  
  2. {  
  3.     if ((r-p)>=50) // 小於50個數據的數組進行插入排序  
  4.     {  
  5.         int q = (p+r)/2;  
  6.         MergeSort2(a, p, q);  
  7.         MergeSort2(a, q+1, r);  
  8.         Merge(a, p, q, r);  
  9.     }else  
  10.     {  
  11.         InsertionSort(a+p, r-p+1);  
  12.     }  
  13. }  

MergeSort1與MergeSort2算法排序時間實驗結果比較:

數據量

1K

10K

100K

1000K

10000K

MergeSort1

0.001s

0.008s

0.065s

0.552s

5.875s

MergeSort2

<0.001s

0.001s

0.021s

0.219s

2.317s



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