歸併 Merge Sort 排序演算法

2021-07-15 00:25:13 字數 2724 閱讀 2459

歸併排序(merge sort)是利用"歸併"技術來進行排序的。歸併是指將若干個已排序的子檔案合併成乙個有序的檔案。

1、歸併排序的基本思想

兩個歸併演算法的基本思想:設有兩個有序的子檔案(相當於輸入堆)放在同一向量中相鄰的位置上:a[low...m],a[m+1...high],先將他們合併到乙個暫存的向量temp(相當於 輸出堆)中,待合併完成後將temp複製回a[low...high]中。

歸併排序有兩種實現方法:自底向上和自頂向下。

自底向上方法的基本思想:

(1) 第1趟歸併排序時,將待排序的檔案a[1...n]看作n個長度為1的有序子檔案,將這些子檔案兩兩歸併。若n為偶數,則得到n/2個長度為2的有序子檔案;若n為奇數,則 最後乙個子檔案不參與歸併。所以本趟歸併完成後,前n/2個有序子檔案長度為2,但最後乙個子檔案長度為1。

(2) 第2趟歸併則是將第1趟歸併所得到的n/2個有序的子檔案兩兩歸併,如此反覆,直到最後得到乙個長度為n的有序檔案為止。

(3) 上述每次歸併操作,均是將兩個有序的子檔案合併成乙個有序的子檔案,所以稱為"二路歸併排序"。類似地,有k(k>2)路歸併排序。

自頂向下方法的基本思想更為簡潔:設歸併排序的當前區間是a[low...high],步驟如下:

(1) 分解:將當前的區間一分為而,即求**點。

(2) 求解:遞迴地對兩個子區間a[low...mid]和a[mid+1...high]進行歸併排序。

(3) 組合:將已排序的兩個子區間a[low...mid]和a[mid+1...high]歸併為乙個有序的區間r[low...high]。

(4) 遞迴的終止條件:子區間長度為1(乙個記錄自然有序)。

2、思想

多次將兩個或兩個以上的有序表合併成乙個新的有序表。 

3、演算法複雜度

最好的情況下:一趟歸併需要n次,總共需要logn次,因此為o(n*logn)

最壞的情況下,接近於平均情況下,為o(n*logn)

說明:對長度為n的檔案,需進行logn 趟二路歸併,每趟歸併的時間為o(n),故其時間複雜度無論是在最好情況下還是在最壞情況下均是o(nlgn)。

4、穩定性

歸併排序最大的特色就是它是一種穩定的排序演算法。歸併過程中是不會改變元素的相對位置的。

缺點是,它需要o(n)的額外空間。但是很適合於多鍊錶排序。(例如將兩個有序鍊錶合併成乙個有序的鍊錶)

5、**實現

//實現歸併排序的演算法(使用自頂向下的方法)

//歸併排序是複雜的排序。

//1.在歸併排序之前,先分配乙個陣列長度大小的臨時空間,用於存放陣列歸併排序的結果.

//2.先將整個陣列每次二分,二分的終止條件是低位下標大於等於高位,遞迴呼叫直到終止.

//3.呼叫歸併時,傳入左側開始位置、右側開始位置和右側結束位置,臨時陣列開始位置為左側位置,左側結束位置為右側開始位置-1

//4.確定臨時陣列長度為右末-左初+1.

//5.先從左初位置和右初位置開始遍歷,比較兩端的元素值,把較小的值放入temp臨時陣列中,再從中找出次小的值存入陣列中,直到左初位置大於左末,或者是右初位置大於右末位置。

//6.不管怎麼操作肯定會有一段含有剩餘元素,遍歷左初到左末,右初到右末位置,把剩餘元素放入陣列中

//7.把臨時陣列中的資料拷貝到原始陣列中,迴圈次數為陣列長度,從右末位置開始。

//8.迴圈2-8步,直到原始陣列有序為止。

#includeusing namespace std;

//將分值的兩端按大小次序填入臨時陣列,最後臨時陣列拷貝到原始陣列中

//lpos到rpos-1為一端,rpos到rend為另外一端

static void merge(int a, int temp, int lpos, int rpos, int rend)

//到這裡,左端大或者右端只能有一端還可能含有剩餘元素

while (lpos <= lend) //把左端剩餘的元素放入temp中

temp[temppos++] = a[lpos++];

while (rpos <= rend) //把右端剩餘的元素放入temp中

temp[temppos++] = a[rpos++];

for (i = 0; i < numelement; i++, rend--)

a[rend] = temp[rend]; //把臨時陣列拷貝到原始陣列中

}static void msort(int a, int temp, int low, int high)

static void merge_sort(int a, int len)

}static void print_array(int a, int length)

}void main9mian****i7()

; cout << "before merge sort:";

print_array(a, 8);

merge_sort(a, 8); //歸併排序

cout << "\nafter merge sort:";

print_array(a, 8);

system("pause");

}

6、測試結果

before merge sort::8 6 1 3 5 2 7 4

after merge sort:1 2 3 4 5 6 7 8 

歸併排序演算法 MergeSort

按著演算法導論的講解,自己去嘗試編這個程式,主體其實早好了,全敗在細節上。於是乎改了又改,就是不知道自己的錯在哪兒,後來又網搜另外一下其他人的程式,發現竟沒找到和我一樣方法的程式,最後只能試著自己改,最後總算執行了。執行最壞情況時間代價為nlgn.另外此為輸入10數字排序。include inclu...

排序演算法 歸併排序(MergeSort)

歸併排序的特點 遞迴的應用 需要準確並深入的理解遞迴的思想 include include define num 8 using namespace std void msort int a,int tmpa,int left,int right int mergesort int a,int n ...

排序演算法 歸併排序 MergeSort

介紹 歸併排序是採用分治法的乙個非常典型的應用。歸併排序的思想就是先遞歸分解陣列,再合並陣列。先考慮合併兩個有序陣列,基本思路是比較兩個陣列的最前面的數,誰小就先取誰,取了後相應的指標就往後移一位。然後再比較,直至乙個陣列為空,最後把另乙個陣列的剩餘部分複製過來即可。再考慮遞迴分解,基本思路是將陣列...