演算法之歸併排序

2021-09-12 07:59:16 字數 2053 閱讀 9733

歸併排序是分治法(divide-and-conquer)的經典案例。

分治模式在每一層遞迴上都有三個步驟:

分解(divide):將原問題分解成一系列子問題;

解決(conquer):遞迴地解各子問題。若子問題足夠小,則直接求解;

合併(combine):將子問題的結果合併成原問題的解。

歸併排序(merge-sort)演算法完全依照了上述模式,具體的操作細節如下圖:

合併的程式偽**如下:

其中a表示待排序的陣列,兩個待合併的區間l和r分別為[p,q]和[q+1,r]

l[n1+1] = int_max和r[n2+1] = int_max是為了設定「哨兵」表示演算法邊界

merge(a,p,q,r)

n1=q-p+1

n2=r-q

let l[1..n1+1] and r[1..n2+1] be new arrays

for i =1 to n1

l[i] = a[p+i-1]

for j = 1 to n2

r[j] = a[q+j]

l[n1+1] = int_max

r[n2+1] = int_max

i=1j=1

for k = p to r

if l[i] =< r[j]

a[k] = l[i]

i = i+1

else a[k] = r[j]

j=j+1

比如對陣列(4,5,7,8,1,2,3,6)進行歸併排序,其merge過程如下圖所示:

(注:上圖來自

完整的歸併排序呼叫merge子程式

merge-sort(a,p,r)

if p < r

q=floor((p+r)/2)

merge-sort(a,p,q)

merge-sort(a,q+1,r)

merge(a,p,q,r)

c++**如下:

同時,merge過程已被改寫,不再使用哨兵元素,而是在一旦陣列l或r中的所有元素都被賦值回陣列a後,就立刻停止,再將另乙個陣列中餘下的元素複製回陣列a中。

#include#includeusing namespace std;

void merge(int a,int begin,int mid,int end)

else }

while(i<=mid)

while(j<=end)

for(i=0;i=end ) return;//一定要=號表示邊界條件

int mid=(begin+end)/2;

mergesort_up(a,begin,mid);//先遞迴分區間

mergesort_up(a,mid+1,end);

merge(a,begin,mid,end);//再合併排序

}

儘管合併排序的最壞情況執行時間為o(nlgn),插入排序的最壞情況執行時間為o(n²),但插入排序中的常數因子使得它在n較小時,執行得要快一些。因此,在合併排序演算法中,當子問題足夠小時,採用插入排序就比較合適了。

void mergesort_insertion(int *a, int p, int r)

else

}

其中mergesort_insertion和原mergesort_up的演算法執行時間比較為:

(注:上述資料來自

演算法之歸併排序

歸併排序 void mergearray int a,int temp,int left,int mid,int right else while i1 mid while i2 right for int i 0 i k i 上面 為合併a left,mid 和a mid 1,right 的 因為...

排序演算法之歸併排序

歸併排序也是經典的使用分治法思想的代表演算法之一。歸併排序的效率很高,而且是一種穩定的排序。其總體的思想思路就是將待排序的元素分成大致相同的兩個子集合,分別對兩個子集合進行排序,最終將排序的子集合合併成排好序的總集合 歸併排序c 實現如下 include void mergesort int arr...

排序演算法之歸併排序

歸併排序是建立在歸併操作上的一種有效的排序演算法。該演算法是採用分治法 divide and conquer 的乙個非常典型的應用,歸併排序將兩個已排序的表合併成乙個表。歸併排序基本原理 通過對若干個有序結點序列的歸併來實現排序。所謂歸併是指將若干個已排好序的部分合併成乙個有序的部分。歸併排序基本思...