將兩個排序好的陣列歸併過程如下:
紅色的 1 是左邊起始位置;
綠色的 2 是右邊起始位置;
灰色的 最右邊 是右邊終點位置;
#include
using
namespace std;
typedef
int elementtype;
//l = 左邊起始位置, r = 右邊起始位置, rightend = 右邊終點位置
void
merge
(elementtype a[
], elementtype tmpa,
int l,
int r,
int rightend)
while
(l <= leftend)
//剩下的陣列全加上去
tmpa[i++
]= a[l++];
while
(r <= rightend)
//剩下的陣列全加上去
tmpa[i++
]= a[r++];
for(
int i =
0; i <= len; i++
,rightend--
) a[rightend]
= tmpa[rightend];}
void
msort
(elementtype a[
], elementtype tmpa,
int l,
int rightend)
//要排序的部分為 l 到 rightend
}void
merge_sort
(elementtype a,
int n)
//用堆申請記憶體排序完再 free 就不會浪費棧記憶體了
else
cout <<
"空間不足";}
intmain()
;int len =
sizeof
(a)/
sizeof
(a[0])
;merge_sort
(a, len)
;for
(int i =
0; i < len; i++
) cout << a[i]
<<
" ";
return0;
}
通過使用分治演算法的思想來對陣列進行排序(這裡叫做歸併排序),分治演算法的核心思想就是把乙個問題分解n個小問題,然後把這n個小問題分別解決,最後再把這n個小問題的結果合併便可以得到結果了。(分解–解決–合併)
此題思路是:
先將乙個未排列的陣列二分、二分、再二分,當分到只有乙個元素時再歸併,歸併就是將原來二分的兩個陣列合併成乙個,歸併的時候順便排序(歷遍兩個陣列排到乙個陣列上),重複此操作,二分多少次就歸併多少次,最後得到的就是乙個排好序陣列
對n個元素進行排序的時間複雜度:
t
(n)=2*
t(n/2)
+ a * n (a是常數,具體多少不重要)=2
*(2*
t(n/4)
+ a * n/2)
+a * n=4
*t(n/4)+
2a * n=4
*(2*
t(n/8)
+ a * n/4)
+2* a * n=8
*t(n/8)+
3* a * n……=
2k *
t(n/
2k)+ k * a * n
一直到n/
2k =
1(此時k = log2n)
t(n)
=2k *t(
1)+ k * a * n
=2k + k * a * n
= n + a *
(log2n)
* n故複雜度為 o
(n * logn)
歸併排序(分治)
把乙個陣列 a 分成兩個部分 s,m m 1,e 假設兩部分分別有序,把這兩部分合併到另一陣列中 tmp 保證該陣列有序,然後再把資料 e s 1拷貝回陣列a 分治的原理。把資料無限二分,最後比較兩個數即可。遞迴實現。includeusing namespace std int a 10 int b...
歸併排序 分治
歸併 將已有序的子串行合併,得到完全有序的序列 即先使每個子串行有 序,再使子串行段間有序。若將兩個有序表合併成乙個有序表,稱為二路歸併。歸併的本質 空間換時間,通過申請乙個額外陣列儲存中間變化,從而實現排序 歸併排序核心步驟 歸併排序的特性總結 歸併的缺點在於需要o n 的空間複雜度,歸併排序的思...
歸併排序 分治
在合併鍊錶的題目中,有乙個典型的題目 合併有序鍊錶 這道題的解法有很多,比較典型的解法是 分治法。這道題的題幹已經給出了重要的資訊 每乙個鍊錶的區域性是有序的。那麼,解決這道題時就可以利用這個特點,不用將每乙個元素逐個比較,可以將鍊錶兩兩排序合併。鍊錶兩兩排序合併有什麼好處?鍊錶兩兩排序可以降低比較...