歸併排序完全遵循分治模式,主要操作分為三步:
1.分解:分解待排序的n個元素序列為2個n/2個元素的子串行。
2.解決:使用歸併排序遞迴的排序兩個子串行。
3.合併:合併兩個已排序的子串行。
最重要的步驟就是合併2個已經排序的序列。例如:a和b都是從小到大排序的序列。依次對比a的第乙個元素和b的第乙個元素,把其中較小的元素出序列,插入到c中,直到兩個序列中的元素都為空。最後,c序列就是乙個包含a序列和b序列且從小到排序的序列。
偽碼:
1view codemerge(a,p,q,r)
2 n1 = q - p + 1
3 n2 = r -q
4 let l[1..n1 + 1] and r[1.. n2 + 1] be new
arrays
5for i = 1
to n1
6 l[i] = a[p + i - 1]7
for j = 1
to n2
8 r[i] = a[q +j]
9 l[n1 + 1] =∞
10 r[n2 + 1] =∞
11 i = 1
12 j = 1
13for k =p to r
14if l[i] <=r[j]
15 a[k] =l[i]
16 i = i + 1
17else
18 a[k] =r[i]
19 j = j + 1
上述偽碼中,其中a為待排序的陣列,且a[p..q ]和a[q + 1..r]都是排序好的。9,10行中,在l,r最後插入乙個值,作為哨兵值,每當出現哨兵值時,它不可能為較小的值,這樣可以簡化**,避免檢查l或r為空。
圖例:
最後我們使用merge_sort 排序陣列a[p...r]中的元素。若p >= r,時,陣列中最多只有乙個元素,所以是排序好的,程式結束;否則,分解陣列a[p...r]為兩個子陣列a[p...q]和a[q + 1...r],然後合併2個子陣列。
偽碼:
1view codemerge_sort(a,p,r)
2if p
3 q = ⌊(p + r) / 2⌋4
merge_sort(a,p,q)
5 merge_sort(a,q + 1
,r)6 merge(a,p,q,r)
圖例:
歸併排序的時間複雜度:t(n) = o(nlgn)
c++**:
1view codevoid merge(int a,int p,int q,intr)2
11for(int i = 0;i < n2;i++)
1215
16for(int k = p,il = 0,ir = 0; k <= r;k++)
1731
else
3237}38
}39 delete (l -n1);
40 delete (r -n2);41}
4243
//合併排序,t(n) = o(nlgn)
44void merge_sort(int a,int p,int
r)45
53 }
排序演算法 歸併排序
歸併排序是建立在歸併操作上的一種有效的排序演算法。該演算法是採用分治法 divide and conquer 的乙個非常典型的應用。首先考慮下如何將將二個有序數列合併。這個非常簡單,只要從比較二個數列的第乙個數,誰小就先取誰,取了後就在對應數列中刪除這個數。然後再進行比較,如果有數列為空,那直接將另...
排序演算法 歸併排序
include include define status int define max 20 typedef struct elemtype typedef struct sqlist void inital sqlist l 初始化 bool lt int i,int j void merge ...
排序演算法 歸併排序
歸併排序的思想其實完全是分治法的思想的體現,它完全遵循分治法的模式。這裡有必要再重提下分治法的思想 將原有的問題分解為幾個規模較小的但類似於原問題的子問題,遞迴的求解這些子問題,然後再合併這些子問題的解來求得原問題的解。現在來看看歸併排序的操作 1 將等待排序的含有 n 個元素的序列分解成各具有 n...