C語言排序演算法之歸併排序

2021-10-04 06:04:39 字數 2512 閱讀 2236

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

設兩個有序的子檔案(相當於輸入堆)放在同一向量中相鄰的位置上:r[low…m],r[m+1…high],先將它們合併到乙個區域性的暫存向量r1(相當於輸出堆)中,待合併完成後將r1複製回r[low…high]中。

(1)合併過程

合併過程中,設定i,j和p三個指標,其初值分別指向這三個記錄區的起始位置。合併時依次比較r[i]和r[j]的關鍵字,取關鍵字較小的記錄複製到r1[p]中,然後將被複製記錄的指標i或j加1,以及指向複製位置的指標p加1。

重複這一過程直至兩個輸入的子檔案有乙個已全部複製完畢(不妨稱其為空),此時將另一非空的子檔案中剩餘記錄依次複製到r1中即可。

最後,將結果賦值到r中。

(2)動態申請r1

實現時,r1是動態申請的,因為申請的空間可能很大,故須加入申請空間是否成功的處理。

自底向上自頂向下方法。

(1) 自底向上的基本思想

自底向上的基本思想是:第1趟歸併排序時,將待排序的檔案r[1…n]看作是n個長度為1的有序子檔案,將這些子檔案兩兩歸併,若n為偶數,則得到 n/2

n/2n/

2 個長度為2的有序子檔案;若n為奇數,則最後乙個子檔案輪空(不參與歸併)。故本趟歸併完成後,前 log

(n)log(n)

log(n)

個有序子檔案長度為2,但最後乙個子檔案長度仍為1;第2趟歸併則是將第1趟歸併所得到的 log

(n)log(n)

log(n)

個有序的子檔案兩兩歸併,如此反覆,直到最後得到乙個長度為n的有序檔案為止。

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

>2)

k(k>2)

k(k>2)

路歸併排序。

(2) 一趟歸併演算法

分析:在某趟歸併中,設各子檔案長度為length(最後乙個子檔案的長度可能小於length),則歸併前r[1…n]中共有 n/l

engt

hn/length

n/leng

th個有序的子檔案:r[1…length],r[length+1…2length],…

注意:呼叫歸併操作將相鄰的一對子檔案進行歸併時,必須對子檔案的個數可能是奇數、以及最後乙個子檔案的長度小於length這兩種特殊情況進行特殊處理:

① 若子檔案個數為奇數,則最後乙個子檔案無須和其它子檔案歸併(即本趟輪空);

② 若子檔案個數為偶數,則要注意最後一對子檔案中後一子檔案的區間上界是n。

舉個栗子:對於陣列 a[n] = ,採用自底向上方法歸併排序過程如下圖所示。

具體實現如下:

int min(int x, int y) 

void merge_sort(int arr, int len)

int *temp = a;

a = b;

b = temp;

}if (a != arr)

free(b);

}

採用分治法進行自頂向下的演算法設計,形式更為簡潔。

(1)分治法的三個步驟

設歸併排序的當前區間是r[low…high],分治法的三個步驟是:

①分解:將當前區間一分為二,即求**點:mid = (low+high)/2;

②求解:遞迴地對兩個子區間r[low…mid]和r[mid+1…high]進行歸併排序;

③組合:將已排序的兩個子區間r[low…mid]和r[mid+1…high]歸併為乙個有序的區間r[low…high]

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

具體實現如下:

void merge_sort(int arr, int low, int high)

}

1、穩定性

歸併排序是一種穩定的排序。

2、儲存結構要求

可用順序儲存結構。也易於在鍊錶上實現。

3、時間複雜度

對長度為n的檔案,需進行 log

(n)log(n)

log(n)

趟二路歸併,每趟歸併的時間為 o(n

)o(n)

o(n)

,故其時間複雜度無論是在最好情況下還是在最壞情況下均是 o(n

logn

)o(nlogn)

o(nlog

n)。4、空間複雜度

需要乙個輔助向量來暫存兩有序子檔案歸併的結果,故其輔助空間複雜度為o(n),顯然它不是就地排序。

注意

若用單鏈表做儲存結構,很容易給出就地的歸併排序。

排序演算法之歸併排序

歸併排序也是經典的使用分治法思想的代表演算法之一。歸併排序的效率很高,而且是一種穩定的排序。其總體的思想思路就是將待排序的元素分成大致相同的兩個子集合,分別對兩個子集合進行排序,最終將排序的子集合合併成排好序的總集合 歸併排序c 實現如下 include void mergesort int arr...

排序演算法之歸併排序

歸併排序是建立在歸併操作上的一種有效的排序演算法。該演算法是採用分治法 divide and conquer 的乙個非常典型的應用,歸併排序將兩個已排序的表合併成乙個表。歸併排序基本原理 通過對若干個有序結點序列的歸併來實現排序。所謂歸併是指將若干個已排好序的部分合併成乙個有序的部分。歸併排序基本思...

排序演算法之歸併排序

歸併排序,和快排一樣同樣採用了分治的思想,將兩個 或以上 有序表合併成乙個新的有序表。歸併排序步驟如下 把n個記錄看成 n個長度為 1 的有序子表 進行兩兩歸併使記錄關鍵字有序,得到 n 2 個長度為 2 的有序子表 重複第2步直到所有記錄歸併成乙個長度為n的有序表為止。下面是歸併排序演算法的遞迴實...