排序演算法系列之合併排序

2021-06-14 04:46:07 字數 2689 閱讀 8937

歸併排序(merge sort,合併排序)是建立在歸併操作上的一種有效的排序演算法。該演算法是採用分治法(divide and conquer)的乙個非常典型的應用。

歸併操作(merge),指的是將兩個已經排序的序列合併成乙個序列的操作,歸併排序演算法依賴歸併操作。

歸併操作的過程如下:

申請空間,使其大小為兩個已經排序序列之和,該空間用來存放合併後的序列

設定兩個指標,最初位置分別為兩個已經排序序列的起始位置

比較兩個指標所指向的元素,選擇相對小的元素放入到合併空間,並移動指標到下一位置

重複步驟3直到某一指標達到序列尾

將另一串行剩下的所有元素直接複製到合併序列尾

void merge(seqlist r,int low,int m,int high)

//merge

歸併排序是基於歸併操作的排序演算法,有多路歸併排序、兩路歸併排序 , 可用於內排序,也可以用於外排序

設兩個有序的子檔案(相當於輸入堆)放在同一向量中相鄰的位置上:r[low..m],r[m+1..high],先將它們合併到乙個區域性的暫存向量r1(相當於輸出堆)中,待合併完成後將r1複製回r[low..high]中。

(1)合併過程

合併過程中,設定i,j和p三個指標,其初值分別指向這三個記錄區的起始位置。合併時依次比較r[i]和r[j]的關鍵字,取關鍵字較小的記錄複製到r1[p]中,然後將被複製記錄的指標i或j加1,以及指向複製位置的指標p加1。

重複這一過程直至兩個輸入的子檔案有乙個已全部複製完畢(不妨稱其為空),此時將另一非空的子檔案中剩餘記錄依次複製到r1中即可。

(2)動態申請r1

實現時,r1是動態申請的,因為申請的空間可能很大,故須加入申請空間是否成功的處理。

自底向上的方法

(1) 自底向上的基本思想

自底向上的基本思想是:第1趟歸併排序時,將待排序的檔案r[1..n]看作是n個長度為1的有序子檔案,將這些子檔案兩兩歸併,若n為偶數,則得到

上述的每次歸併操作,均是將兩個有序的子檔案合併成乙個有序的子檔案,故稱其為"二路歸併排序"。類似地有k(k>2)路歸併排序。

(2) 二路歸併排序的演算法演示

【參見動畫演示

】(3) 一趟歸併演算法

分析:在某趟歸併中,設各子檔案長度為length(最後乙個子檔案的長度可能小於length),則歸併前r[1..n]中共有

r[1..length],[length+1..2length],…,

注意:呼叫歸併操作將相鄰的一對子檔案進行歸併時,必須對子檔案的個數可能是奇數、以及最後乙個子檔案的長度小於length這兩種特殊情況進行特殊處理:

① 若子檔案個數為奇數,則最後乙個子檔案無須和其它子檔案歸併(即本趟輪空);

② 若子檔案個數為偶數,則要注意最後一對子檔案中後一子檔案的區間上界是n。

具體實現演算法:

void mergepass(seqlist r,int length)

{ //對r[1..n]做一趟歸併排序

int i;

for(i=1;i+2*length-1<=n;i=i+2*length)

merge(r,i,i+length-1,i+2*length-1);

//歸併長度為length的兩個相鄰子檔案

if(i+length-1(4)二路歸併排序演算法

void mergesort(seqlist r)

{//採用自底向上的方法,對r[1..n]進行二路歸併排序

int length;

for(1ength=1;length注意:

自底向上的歸併排序演算法雖然效率較高,但可讀性較差。

自頂向下的方法

採用分治法進行自頂向下的演算法設計,形式更為簡潔。

(1)分治法的三個步驟

設歸併排序的當前區間是r[low..high],分治法的三個步驟是:

①分解:將當前區間一分為二,即求**點

②求解:遞迴地對兩個子區間r[low..mid]和r[mid+1..high]進行歸併排序;

③組合:將已排序的兩個子區間r[low..mid]和r[mid+1..high]歸併為乙個有序的區間r[low..high]。

遞迴的終結條件:子區間長度為1(乙個記錄自然有序)。

(2)具體演算法

void mergesortdc(seqlist r,int low,int high)

{//用分治法對r[low..high]進行二路歸併排序

int mid;

if(low

(3)演算法mergesortdc的執行過程

演算法mergesortdc的執行過程如下圖所示的遞迴樹。

歸併排序示例: 自頂向下的二路歸併的執行過程

乙個歸併排序的例子:對乙個隨機點的鍊錶進行排序:

1、穩定性

歸併排序是一種穩定的排序。

2、儲存結構要求

可用順序儲存結構。也易於在鍊錶上實現。

3、時間複雜度

對長度為n的檔案,需進行

4、空間複雜度

需要乙個輔助向量來暫存兩有序子檔案歸併的結果,故其輔助空間複雜度為o(n),顯然它不是就地排序。

1. 兩路歸併:

2. 維基百科:

3. 演算法導論

排序演算法系列之歸併排序

public class mergesort if index1 middle while index2 high else while index1 middle 將temp low high 序列複製到原序列 system.arraycopy temp,low,array,low,high 1 ...

排序法系列之四 合併排序法

分治策略 將原問題劃分為n個規模較小而結構與原問題相似的的子問題,遞迴地解決這些子問題,然後再合併這些結果,就得到原問題的解。分支策略在每層遞迴上都實現以下三個步驟 分解 將原問題劃分為多個子問題。解決 遞迴地解決各個子問題。若子問題足夠小,則直接求解 合併 將子問題的結果合併成原問題的解。合併排序...

排序演算法系列 1 歸併排序

知識點 歸併排序 歸併排序是建立在歸併操作上的一種有效的排序演算法。該演算法是採用分治法 divide and conquer 的乙個非常典型的應用。歸併排序是一種穩定的排序方法。將已有序的子串行合併,得到完全有序的序列 即先使每個子串行有序,再使子串行段間有序。若將兩個有序表合併成乙個有序表,稱為...