歸併
:將兩個或兩個以上的有序表組合成乙個新有序表。
基本思路:
歸併排序採用了分治策略(divide-and-conquer),就是將原問題分解為一些規模較小的相似子問題,然後遞迴解決這些子問題,最後合併其結果作為原問題的解。(也就是
將已有序的子串行合併,得到完全有序的序列;即先使每個子串行有序,再使子串行段間有序。若將兩個有序表合併成乙個有序表
,稱為二路歸併
。)先遞迴的把陣列劃分為兩個子陣列,一直遞迴到陣列中只有乙個元素,然後再呼叫函式把兩個子陣列排好序,因為該函式在遞迴劃分陣列時會被壓入棧,所以這個函式真正的作用是對兩個有序的子陣列進行排序;
基本步驟
就是將陣列分成二組a,b,如果這兩組組內的資料都是有序的,那麼就可以很方便的將這兩組資料進行排序。如何讓這二組組內資料有序了?
可以將a,b組各自再分成兩組。依次類推,
當分出來的小組只有乙個資料時(即為該層遞迴的返回條件,此時first=last)
,可以認為這個小組組內已經達到了有序,然後再合併相鄰的兩個小組就可以了。這樣通過先遞迴
的分解數列,再合併
數列就完成歸併
排序。首先考慮下如何將將兩個有序數列合併。這個非常簡單,只要從比較兩個數列的第乙個數,誰小就先取誰,取了後就在對應數列中刪除這個數。然後再進行比較,如果有數列為空,那直接將另乙個數列的資料依次取出即可。
//將有序陣列a和b合併到c中
void memeryarray(int a, int n, int b, int m, int c)
while (i < n)
c[k++] = a[i++];
while (j < m)
c[k++] = b[j++];
}
時間複雜度為o(n)
再看歸併的操作:先遞迴分解數列,再對數列合併排序,
每層遞迴的返回條件就是last=first,即此分組中只有乙個元素:
//將有兩個有序數列a[first...mid]和a[mid...last]合併。
void mergearray(int a, int first, int mid, int last, int temp)
{ int i=first, j=mid+1;
int m=mid, n=last;
int k=0;
while(i<=m&&j<=n)
{ if(a[i]
時間複雜度
歸併排序的過程圖與完全二叉樹十分相似,演算法中把記錄掃瞄一遍耗費o(n),
又由完全二叉樹的深度知:整個歸併排序需要[log2 n]次,故總的時間複雜度為o(n * log n)
換句話說,設數列長n,將數列分為小數列需要log n次,每一步都在合併有序數列,時間複雜度為o(n),
故總的時間複雜度為o(n * log n) (同時間複雜度的還有希爾排序,堆排序,快速排序,歸併排序效率較高)
空間複雜度
歸併排序在歸併過程中需要與原始記錄序列同等數量的儲存空間存放歸併結果以及遞迴時深度為log2 n的棧空間,
故空間複雜度o(n + log n)
穩定性mergearray()
該函式中有if(a[i]
綜上,歸併排序是一種比較占用記憶體,但效率高且穩定的演算法
測試**:
#include#include//歸併排序
//將兩個有序數列a[first...mid]和a[mid...last]合併。
void mergearray(int a, int first, int mid, int last, int temp)
{ int i=first, j=mid+1;
int m=mid, n=last;
int k=0;
while(i<=m&&j<=n)
{ if(a[i]
專案計畫的失敗有跡可循
丹尼爾 康納曼 daniel kahneman 在他的管理學著作 快思慢想 thinking fast and slow 裡,提到了 段他和他在以色列教育部的同事曾面臨的困境,當時他們必須估算,編輯一本有關判斷與決策的中學教科書可能要花多少時間。當他們的團隊估算完成那本教科書所需的時間時,最後得到的...
歸併排序(2 路歸併排序)
遞迴寫法 include define maxn 100 void merge int a,int l1,int r1,int l2,int r2 將陣列a的區間 l1,r1 和區間 l2,r2 合併為乙個有序區間 else while i r1 while j r2 for int i 0 i非遞...
python歸併排序 python 歸併排序
排序思路 1.將陣列分成兩組a,b,建立臨時陣列 c,c長度 a b 2.i,j分別屬於a,b 3.若a i b j 將b j 放入c,j 否則 a i 放入c,i 4.迴圈3步驟,將a或b中剩餘的元素放入c,再將c複製到陣列中 5.遞迴3 4直到a,b序列的長度 1 歸併排序 class merg...