排序演算法(2)——歸併排序

來源:互聯網
上載者:User

歸併排序(Merge Sort)

   (1)演算法思想

             歸併排序採用了分治策略(divide-and-conquer),就是將原問題分解為一些規模較小的相似子問題,然後遞迴解決這些子問題,最後合并其結果作為原問題的解。

              歸併排序將待排序數組A[1..n]分成兩個各含n/2個元素的子序列,然後對這個兩個子序列進行遞迴排序,最後將這兩個已排序的子序列進行合并,即得到最終排好序的序列。具體排序過程如下圖所示:


             歸併排序中一個很重要的部分是兩個已排序序列合并的過程,這裡需要另外開闢一塊新的空間來作為儲存這兩個已排序序列的臨時容器。假設對A[p..r]序列進行合并,已知A[p..q]及A[q+1..r]為已排序的序列,合并的具體步驟為:

            Step 1:建立兩個數組L、R分別儲存待定序序列A[p..q]和A[q+1..r],將待排序序列中的對應元素copy到L和R中,L和R最後設定一個極大值作為“哨兵”;

           Step 2:令指標i指向L的起始元素,j指向R的起始元素,k指向A待合并部分的起始元素A[p];

           Step 3:若L[i]≤R[j],令A[k]=L[i],i=i+1,k=k+1;

                         否則,令A[k]=R[j],j=j+1,k=k+1;

                        (這一步即依次比較i、j所指向的元素,將較小值依次放入到A中相應位置。)

          Step 4 :重複Step 3,r-p+1次後停止,即依次確定A[p..q]每個位置上的元素。

         經過合併作業後,A[p..q]為一個有序序列。若待定序序列為(38, 49, 65, 97, 13, 27, 49, 76),p=1,q=4,, r=8,即A[1..4]和A[5..8]分別為有序序列,則合併作業的具體過程如下圖所示:



    (2)虛擬碼

             MERGE SORT(A, p, r)                                    //對A[p..r]進行歸併排序
             1 if  p < r
             2     then q ← ⎣(p+r)/2⎦                                     //將A[p..r]分成兩個子序列進行遞迴歸併排序
             3             MERGE-SORT (A, p, q)
             4             MERGE-SORT (A, q+1, r)
             5             MERGE (A, p, q, r)                           //將已排序的兩個子序列進行合并


             MERGE(A, p, q, r)
             1 n1 ← q-p+1;                                                  //計算左半部分已排序序列的長度
             2 n2 2 ← r-q;                                                    //計算右半部分已排序序列的長度
             3 create arrays L[1..n1+1] and R[1..n2+1]      //建立兩個數組臨時儲存兩個已排序序列,長度+1是因為最後有一個標誌位
             4 for i ← 1 to n1
             5      do L[i] ← A[p + i-1]                                //copy左半部分已排序序列到L中
             6 for j ← 1 to n2
             7      do R[j] ← A[q + j]                                   //copy右半部分已排序序列到R中
             8 L[n1+1] ← ∞                                                //L、R最後一位設定一個極大值作為標誌位                       
             9 R[n2+1] ← ∞
            10 i ← 1
            11 j ← 1
            12 for k ← p to r                                              //進行合并
            13      do if L[i] < R[j]
            14          then A[k] ← L[i]
            15                  i ← i + 1
            16          else A[k] ← R[j]
            17                  j ← j + 1

          

    (3)代碼實現

             注意,開始排序時,p、r表示的是待排序數組的起始下標和終止下標,例如,若A=(38, 49, 65, 97, 13, 27, 49, 76),對A進行排序,調用MergeSort(A, 0, 7),即p=0, r=7.

void Merge(int A[],int p,int q,int r){    int i,j,k;    int n1=q-p+1;    int n2=r-q;    int *L=new int[n1+1]; //開闢臨時儲存空間    int *R=new int[n2+1];    for(i=0;i<n1;i++)        L[i]=A[i+p];      //數組下標從0開始時,這裡為i+p    for(j=0;j<n2;j++)        R[j]=A[j+q+1];    //數組下標從0開始時,這裡為就j+q+1    L[n1]=INT_MAX;        //"哨兵"設定為整數的最大值,INT_MAX包含在limits.h標頭檔中    R[n2]=INT_MAX;    i=0;    j=0;    for(k=p;k<=r;k++)     //開始合并    {        if(L[i]<=R[j])            A[k]=L[i++];        else            A[k]=R[j++];    }}void MergeSort(int A[],int p,int r) {    if(p<r)    {        int q=(p+r)/2;        MergeSort(A,p,q);        MergeSort(A,q+1,r);        Merge(A,p,q,r);    }

              通過簡單的變化,L、R也可以不使用“哨兵”,當L中的元素全部填入A中時,後面過程直接將R剩餘部分copy到A中;當R中的元素全部填入A中時,後面過程直接將L剩餘部分copy到A中。具體實現如下:

void Merge2(int A[],int p,int q,int r){    int i,j,k;    int n1=q-p+1;    int n2=r-q;    int *L=new int[n1];     int *R=new int[n2];    for(i=0;i<n1;i++)        L[i]=A[i+p];          for(j=0;j<n2;j++)        R[j]=A[j+q+1];        i=0;    j=0;    for(k=p;k<=r;k++)         {        if(j==n2||L[i]<=R[j])   //注意:此處加了j==n2的或條件            A[k]=L[i++];        else            A[k]=R[j++];    }}

    (4)演算法分析

             a.歸併排序的時間複雜度為:Θ(nlgn),其中 MERGE(A, p, q, r)的時間複雜度為Θ(n)。

             b.歸併排序並不是一種原地排序,因為需要額外申請空間來充當臨時容器。

             c.歸併排序是一種穩定排序。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.