今天學習了演算法導論上的歸併排序演算法,並且完成了在紙上寫出偽**,以前就學過歸併但是理解的不夠透徹,前還一直困惑:為什麼明明歸併排序比快排的時間複雜度更穩定,為什麼庫函式不用歸併而用快排,現在知道原因了,因為歸併排序必須開額外的空間,而且空間開銷還比較大,下面介紹演算法:以
首先,歸併排序用到了分治的思想,把大資料分成若干個小資料,然後再分別對小資料進行處理,最後把小資料合併成大資料。
其次,歸併排序用到了乙個最重要的特點,就是把兩組已經排序的資料合併成一組有序資料,並且該過程的時間復雜度為o(n)。
最後,演算法便出來了,對於乙個陣列a[n]來說,我們要對他進行排序,首先,我們假設a[0~n/2]和a[n/2+1,n-1]為有序序列,
那麼,我們就可以在o(n)的時間內排好序,可是,問題是,a[0~n/2]和a[n/2+1,n-1]並不是有序序列,於是我們就要將他們都變成有序序列,如何變呢?我們再分別對a[0~n/2]和a[n/2+1,n-1]進行排序即可,對於a[0~n/2]來說,我們運用和以上相同的方法,把他分成a[0~n/2/2]和a[n/2+1,n/2],然後如果這兩個陣列均為有序序列的話,那麼就可以把它們合併起來,然後在返回到上一層了,那麼如何才能判斷他們為有序呢?當只有乙個元素的時候這個元素便是有序的,所以,只需要遞迴到元素個數為1,然後再返回合併即可。
下面是對以下下**中的merge()(合併)函式正確性的證明:1.當第一次迴圈迭代的時候,i = l, a[l, i-1]為空,是有序的序列(空也算有序序列),並且含有i-l=0個la[n1],ra[n2]的最小的數,這時c1 = c2 = 0, la[c1]和ra[c2]均為彼此陣列中的最小的元素。
2.假設第i次迭代的時候la[c1] <= ra[c2], 這時la[c1]便是還沒有被複製到a中的最小的元素,此時a中含有i-l個最小的元素,當執行a[i] = la[c1]時,a中便含有i-l+1個最小的元素,然後增加c1和i進行下一次迭代,如果第一次時la[c1] > ra[c2],執行相似的過程。
3.迴圈結束後,i = r+1, 此時a中含有i-l = r-l+1個最小的元素,恰好是l~r所有的元素,並且已排好序,證畢。
//insertion_sort
#include using namespace std;
const int inf = (1<<28);
void print(int* a, int n)
cout << endl;
}void merge(int *a, int l, int m, int r)
for (int i = 0; i < n2; i++)
la[n1] = ra[n2] = inf;
int c1 = 0, c2 = 0;
for (int i = l; i <= r; i++)
else
}}void merge_sort(int *a, int l, int r)
}int main()
;
cout << "before sorted: ";
print(a, 10);
merge_sort(a, 0, 10);
cout << "after sorted: ";
print(a, 10);
return 0;
}
演算法導論學習 歸併排序
前面看完了插入排序和插入排序後面習題裡面的選擇排序,最近又把歸併排序給看了。插入排序的最壞情況為n平方,當然選擇排序的恒為n平法,而歸併排序則是乙個nlogn的時間複雜度。當然這指的是在n無限大的情況下才可以成立,對於元素個數很小的,插入排序反而會快一些。歸併排序的主要思想就是利用了分治法把大的問題...
歸併排序 演算法導論學習
歸併排序利用分治的思想進行排序,採用遞迴形式進行排序 舉個栗子 給乙個五個元素的陣列,下標從0到4 把其分為兩個部分 0,1,2和3,4 兩個部分都有序了再合併 0,1,2再分為兩個部分0,1和2 兩個部分都有序了再合併 比較0,1,的大小使其有序,2是乙個數字,也有序,將這兩個有序的合為乙個有序的...
演算法導論 歸併排序
public class mergesort mergesort data,0,中間 mergesort data,中間,最後 merge data,0,最後 system.out.println 排序前 for int i 0 i9 i 10 0 system.out.println system...