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