《大話資料結構》第9章 排序 9.8 歸併排序(上)_大話資料結構

來源:互聯網
上載者:User
9.8.1 歸併排序介紹

        前面我們講了堆排序,因為它用到了完全二叉樹,充分利用了完全二叉樹的深度是⌊log2n⌋+1的特性,所以效率比較高。不過堆結構的設計本身是比較複雜的,老實說,能想出這樣的結構就挺不容易,有沒有更直接簡單的辦法利用完全二叉樹來排序呢。當然是有。
        先來舉一個例子。你們知道高考一本、二本、專科分數線是如何劃分出來的嗎。
        簡單地說,如果各高校本科專業在某省高三理科學生中計劃招收1萬名,那麼將全省參加高考的理科學生分數倒排序,第1萬名的總分數就是當年本科生的分數線(現實可能會比這複雜,這裡簡化之)。也就是說,即使你是你們班級第一、甚至年級第一名,如果你沒有上分數線,則說明你的成績排不到全省前1萬名,你也就基本失去了當年上本科的機會了。
        換句話說,所謂的全省排名,其實也就是每個市、每個縣、每個學校、每個班級的排名合并後再排名得到的。注意我這裡用到了合并一詞。
我們要比較兩個學生的成績高低是很容易的,比如甲比乙分數低,丙比丁分數低。那麼我們也就可以很容易得到甲乙丙丁合并後的成績排名,同樣的,戊己庚辛的排名也容易得到,由於他們兩組分別有序了,把他們八個學產生績合并有序也是很容易做到的了,繼續下去……最終完成全省學生的成績排名,此時高考狀元也就誕生了。
        為了更清晰地說清楚這裡的思想,大家來看圖9-8-1,我們將本是無序的數組序列{16,7,13,10,9,15,3,2,5,8,12,1,11,4,6,14},通過兩兩合并排序後,再合并,最終獲得了一個有序的數組。注意仔細觀察它的形狀,你會發現,它像極了一棵倒置的完全二叉樹,通常涉及到完全二叉樹結構的排序演算法,效率一般都不低的——這就是我們要講的歸併排序法。
 

 


9.8.2 歸併排序演算法
        “歸併”一詞的中文含義就是合并、併入的意思,而在資料結構中的定義是將兩個或兩個以上的有序表組合成一個新的有序表。
        歸併排序(Merging Sort)就是利用歸併的思想實現的排序方法。它的原理是假設初始序列含有n個記錄,則可以看成是n個有序的子序列,每個子序列的長度為1,然後兩兩歸併,得到⌈n/2⌉(⌈x⌉表示不小於x的最小整數)個長度為2或1的有序子序列;再兩兩歸併,……,如此重複,直至得到一個長度為n的有序序列為止,這種排序方法稱為2路歸併排序。 
        好了,有了對歸併排序的初步認識後,我們來看代碼。

/* 對順序表L作歸併排序 */void MergeSort(SqList *L){   MSort(L->r,L->r,1,L->length);}

        一句代碼,別奇怪,它只是調用了另一個函數而已。為了與前面的排序演算法統一,我們用了同樣的參數定義SqList *L,由於我們要講解的歸併排序實現需要用到遞迴調用 ,因此我們外封裝了一個函數。假設現在要對數組{50,10,90,30,70,40,80,60,20}進行排序,L.length=9,我現來看看MSort的實現。

/* 將SR[s..t]歸併排序為TR1[s..t] */void MSort(int SR[],int TR1[],int s, int t){ int m; int TR2[MAXSIZE+1]; if(s==t)  TR1[s]=SR[s]; else {  m=(s+t)/2;   /* 將SR[s..t]平分為SR[s..m]和SR[m+1..t] */  MSort(SR,TR2,s,m); /* 遞迴地將SR[s..m]歸併為有序的TR2[s..m] */  MSort(SR,TR2,m+1,t); /* 遞迴地將SR[m+1..t]歸併為有序TR2[m+1..t] */  Merge(TR2,TR1,s,m,t); /* 將TR2[s..m]和TR2[m+1..t]歸併到TR1[s..t] */ }}

1) MSort被調用時,SR與TR1都是{50,10,90,30,70,40,80,60,20},s=1,t=9,最終我們的目的就是要將TR1中的數組排好順序。
2) 第5行,顯然s不等於t,執行第8~13行語句塊。
3) 第9行,m=(1+9)/2=5。m就是序列的正中間下標
4) 此時第10行,調用“MSort(SR,TR2,1,5);”的目標就是將數組SR中的第1~5的關鍵字歸併到有序的TR2(調用前TR2為空白數組),第11行,調用“MSort(SR,TR2,6,9);”的目標就是將數組SR中的第6~9的關鍵字歸併到有序的TR2。也就是說,在調用這兩句代碼之前,代碼已經準備將數組分成了兩組了。如圖9-8-2。
 

5) 第12行,函數Merge的代碼細節一會再講,調用“Merge(TR2,TR1,1,5,9);”的目標其實就是將第10和11行代碼獲得的數組TR2(注意它是下標為1~5和6~9的關鍵字分別有序)歸併為TR1,此時相當於整個排序就已經完成了。如圖9-8-3。
 
6) 再來看第10行遞迴調用進去後,s=1,t=5,m=(1+5)/2=3。此時相當於將5個記錄再為三個和兩個。繼續遞迴進去,直到細分為一個記錄填入TR2,此時s與t相等,遞迴返回,如圖9-8-4的左圖。每次遞迴返回後都會執行當前遞迴函式的第12行,將TR2歸併到TR1中。如圖9-8-4的右圖。最終使得當前序列有序。
 

7) 同樣的第11行也是類似方式,如圖9-8-5。
 
8) 此時也就是剛才所講的最後一次執行第12行代碼,將{10,30,50,70,90}與{20,40,60,80}歸併為最終有序的序列。
可以說,如果對遞迴函式的運行方式理解比較透的話,MSort函數還是很好理解的。我們來看看整個資料變換示意圖,如圖9-8-6。
 

現在我們來看看Merge函數的代碼是如何?的。

 

/* 將有序的SR[i..m]和SR[m+1..n]歸併為有序的TR[i..n] */void Merge(int SR[],int TR[],int i,int m,int n){ int j,k,l; for(j=m+1,k=i;i<=m && j<=n;k++) /* 將SR中記錄由小到大歸併入TR */ {  if (SR[i]<SR[j])   TR[k]=SR[i++];  else   TR[k]=SR[j++]; } if(i<=m) {  for(l=0;l<=m-i;l++)   TR[k+l]=SR[i+l];  /* 將剩餘的SR[i..m]複製到TR */ } if(j<=n) {  for(l=0;l<=n-j;l++)   TR[k+l]=SR[j+l];  /* 將剩餘的SR[j..n]複製到TR */ }}

1) 假設我們此時調用的Merge就是將{10,30,50,70,90}與{20,40,60,80}歸併為最終有序的序列,因此數組SR為{10,30,50,70,90,20,40,60,80},i=1,m=5,n=9。
2) 第4行,for迴圈,j由m+1=6開始到9,i由1開始到5,k由1開始每次加1,k值用於目標數組TR的下標。
3) 第6行,SR[i]=SR[1]=10,SR[j]= SR[6]=20,SR[i]<SR[j],執行第7行,TR[k]=TR[1]=10,並且i++。如圖9-8-7。
 

4) 再次迴圈,k++得到k=2,SR[i]=SR[2]=30,SR[j]= SR[6]=20,SR[i]>SR[j],執行第9行,TR[k]=TR[2]=20,並且j++,如圖9-8-8。
 

5) 再次迴圈,k++得到k=3,SR[i]=SR[2]=30,SR[j]= SR[7]=40,SR[i]<SR[j],執行第7行,TR[k]=TR[3]=30,並且i++,如圖9-8-9。
 

6) 接下來完全相同的操作,一直到j++後,j=10,大於9退出迴圈。如圖9-8-10。
 

7) 第11~20行的代碼,其實就將歸併剩下的數組資料,移動到TR的後面。當前k=9,i=m=5,執行第13~20行代碼,for迴圈l=0,TR[k+l]=SR[i+l]=90。大功告成。
        就這樣,我們的歸併排序就算是完成了一次排序工作,怎麼樣,和堆排序比,是不是要簡單一些呢。 出處:http://www.cnblogs.com/cj723/archive/2011/04/25/2026751.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.