演算法導論學習筆記 2 歸併排序

2021-06-27 18:21:15 字數 1819 閱讀 3858

今天學習了演算法導論上的歸併排序演算法,並且完成了在紙上寫出偽**,以前就學過歸併但是理解的不夠透徹,

前還一直困惑:為什麼明明歸併排序比快排的時間複雜度更穩定,為什麼庫函式不用歸併而用快排,現在知道原因了,因為歸併排序必須開額外的空間,而且空間開銷還比較大,下面介紹演算法:

首先,歸併排序用到了分治的思想,把大資料分成若干個小資料,然後再分別對小資料進行處理,最後把小資料

合併成大資料。

其次,歸併排序用到了乙個最重要的特點,就是把兩組已經排序的資料合併成一組有序資料,並且該過程的時間復

雜度為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...