(1 3 5)歸併排序 二路歸併

2021-06-29 04:47:09 字數 2378 閱讀 8895

歸併排序(merge sort)

是將兩個(或兩個以上)有序表合併成乙個新的有序表,即把待排序序列分為若干個有序的子串行,再把有序的子串行合併為整體有序序列。

歸併排序的具體做法:

把原序列不斷地遞迴等分,直至每等份只有乙個元素,此時每等份都是有序的。

相鄰等份合併,不斷合併,直至合併完全。

二路歸併

歸併排序

是建立在歸併操作上的一種有效的排序

演算法。該演算法是採用分治法

(divide and conquer)的乙個非常典型的應用。歸併排序最常用的是二路歸併,即把兩個小的有序的序列和並成乙個大的有序序列:合二為一。

乙個二路歸併的流程圖是這樣的:

多路歸併無非是多個有序的小序列合併成乙個大的有序序列,道理和二路歸併一樣。

先來看下如何把兩個有序的序列合併成乙個大的有序序列,**如下:

[cpp]view plain

copy

/**把有序序列a和b,合併成c 

*該演算法成立前提: a和b已經有序  

*/void

merge(

inta, 

intna, 

intb, 

intnb, 

intc)  

//把a或b中剩餘的元素直接存入c 

/*  也可以這樣:

*  memcpy(c+k, a+i, (na-i)sizeof(int));

* 下同

*/while

(i c[k++] = a[i++];  

while

(j c[k++] = b[j++];  

}  }  

可以看出,二路歸併的時間複雜度是o(n),n是原序列的資料規模。以上**是歸併排序的基礎,弄懂了它,就很好寫歸併排序了,看下歸併排序的流程圖:

可以看出,上半部分不斷地遞迴深入:不斷地均分原序列,直到每一部分只含有乙個元素。下半部分,開始遞迴返回,通過反覆呼叫二路歸併演算法,把相鄰的有序子串行合併成乙個規模更大的序列。

理解了這些,相信就很容易寫出歸併排序的**了:

[cpp]view plain

copy

//把[first, mid]和[mid+1, last]範圍內的資料合併  

void

mergearray(

inta, 

intb, 

intfirst, 

intmid, 

intlast)  

/*  也可以這樣:

*  memcpy(b+k, a+i, (mid-i+1)sizeof(int));

* 下同

*/while

(i <= mid)  

b[k++] = a[i++];  

while

(j <= last)  

b[k++] = a[j++];  

//[first,last]範圍內的資料已有序,則寫回原陣列

for(i = 0; i 

a[first + i] = b[i];  

}  void

mergesort(

inta, 

intb, 

intfirst, 

intlast)  

}  void

mergesort(

inta, 

intn)  

}  在排序過程中,我們使用了乙個相同大小的臨時輔助陣列。

演算法分析:

1.演算法的複雜度

對陣列長度為n的序列進行歸併排序,則大約要進行logn次歸併,每一次合併都是線性時間o(n)。故粗略的計算出歸併排序的時間複雜度是o(nlogn)(最好、最差都是這樣)。空間複雜度是o(n)。

詳細的時間複雜度分析是這樣的:

對長度為n的序列歸併排序,需要遞迴的對長度為n/2的子串行進行歸併排序,最後把兩段子序列二路歸併。遞推關係是這樣的:t(n)=2t(n/2)+o(n),顯然t(1)=o(1),解得t(n)=o(nlogn)。

2.穩定性

歸併排序是穩定的,並且是時間複雜度為o(nlogn)的幾種排序(快速排序、堆排序)中唯一穩定的排序演算法。

3.儲存結構

順序儲存和鏈式儲存都行。

另外,歸併排序多用於外排序中。

歸併排序(二路歸併)

歸併排序是一種遞迴思想的體現,通過多次合併較小的幾個 二路歸併為兩個 有序陣列形成新的有序表。思路 將陣列分為n nn個一元組,兩兩合併得到二元組,以此類推共合併log 2n log 2n log2 n 次後,陣列變得有序。時間複雜度為o n logn o nlogn o nlog n 編譯環境de...

排序 歸併排序(二路歸併)

基本思想 將兩個有序表合併成乙個有序表。將下列兩個已排序的順序表合併成乙個已排序表。順序比較兩 者的相應元素,小者移入另一表中,反覆如此,直至其中任一表都移入另 一表為止。二路歸併排序的基本思想是將兩個有序表合併成乙個有序表。給定排序碼46,55,13,42,94,05,17,70,二路歸併排序過程...

二路歸併排序

不是困難的演算法,不過也是練習了下遞迴。include include include using namespace std const int maxn 100 5 int a maxn int b maxn void mergesort int a,int b,int begin,int en...