【歸並排序】my merge_sort 整理
merge_sort是分治法的一個典型應用。這裏有一張《各類排序算法時間、空間復雜度對比表》,從表中可以看得出,merge_sort(歸並排序算法)是比較穩定的算法,使用較廣泛。求逆序對也是很好用的。
分治過程概括圖:藍色的原始數組,運用merge_sort以後為有序的綠色數組
我的理解:主要想說二路歸並(大佬請忽略)
1. merge() 是二路歸並的階段,簡單來說是有序表的合並。這時有兩段:左段 al~amid 和右段 amid+1~ar ,轉移數組 c 的下標從 cnt=0 開始,定義左右兩段的下標分別為 i 、j ,且 i 指向 al ,j 指向 amid+1
對應code:
const int M=1e5+5;
int a[M];
void Merge(int l,int m,int r)
{
int c[r-l+1];
int i=l,j=m+1;
int cnt=0;
while(i<=m&&j<=r)
{
if(a[i]<=a[j])
c[cnt++]=a[i++];
else
c[cnt++]=a[j++];
}
while(i<=m)
c[cnt ++]=a[i++];
while(j<=r)
c[cnt++]=a[j++];
for(int k=0;k<cnt;k++)
a[l++]=c[k];
}
merge()
2.sort() 內部使用遞歸,遞歸邊界:各有序表長度為 1 ,數組分兩段進行,然後逐步返回,返回過程調用merge()。最終得到有序表a[ ];
對應code:
void mergesort(int l,int r)
{
if(l==r)/*!< 遞歸邊界 */
return;
int m=(l+r)/2;/*!< 遞歸步驟 */
mergesort(l,m);
mergesort(m+1,r);
Merge(l,m,r);/*!< 二路歸並 */
}
mergesort()
那麽整個算法:
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 5 const int M=1e5+5; 6 int a[M]; 7 8 void Merge(int l,int m,int r) 9 { 10 int c[r-l+1]; 11 int i=l,j=m+1; 12 int cnt=0; 13 while(i<=m&&j<=r) 14 { 15 if(a[i]<=a[j]) 16 c[cnt++]=a[i++]; 17 else 18 c[cnt++]=a[j++]; 19 } 20 while(i<=m) 21 c[cnt++]=a[i++]; 22 while(j<=r) 23 c[cnt++]=a[j++]; 24 for(int k=0;k<cnt;k++) 25 a[l++]=c[k]; 26 } 27 28 void mergesort(int l,int r) 29 { 30 if(l==r)/*!< 遞歸邊界 */ 31 return; 32 int m=(l+r)/2;/*!< 遞歸步驟 */ 33 mergesort(l,m); 34 mergesort(m+1,r); 35 Merge(l,m,r);/*!< 二路歸並 */ 36 }Merge sort
PS:這裏有兩歸並可解的題:洛谷【P1177】 模板 快速排序 和 洛谷【P1908】逆序對,供測試。
【歸並排序】my merge_sort 整理