歸併排序是分治法(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 的乙個非常典型的應用,歸併排序將兩個已排序的表合併成乙個表。歸併排序基本原理 通過對若干個有序結點序列的歸併來實現排序。所謂歸併是指將若干個已排好序的部分合併成乙個有序的部分。歸併排序基本思...