歸併排序理解
歸併排序的主要操作如下:
(1)分解。把初始序列分成長度相同的左、右兩個子序列,然後把每個子序列再分成更小的兩個子序列,直到子序列只包含一個數。這個過程用遞歸實現。
(2)求解子問題,對子序列排序。最底層的子序列只包含一個數,其實不用排序。
(3)合併。歸併兩個有序的子序列,這是歸併排序的主要操作。比如下面舉例,把a[ ]分成兩個子序列,比較後存進b[ ],假設兩個子序列已經分別排好序。
過程如下(有點醜…將就一下):
只要有一個子序列結束,就可以把另一個子序列後面的都放進去,因爲是排好序的
歸併排序的時間複雜度:對n個數進行排序:
- 需要log2(n)趟歸併。
- 在每一趟歸併中有很多次合併操作。共需O(n)次比較。所以時間複雜度爲
歸併排序模板
輸入n個數,對n個數進行排序。
#include<iostream>
using namespace std;
const int N=1e6 + 10;
int n;
int q[N],temp[N];
void merge(int q[],int l,int r)
{
if(l >= r) return;//滿足條件不再往下進行
int mid = (l + r)/2;
merge(q,l,mid),merge(q,mid+1,r);//左右分開遞歸
int k=0,i=l,j=mid+1;//k表示temp裏個數,i指向左子序開頭,j指向右子序開頭
while(i <= mid && j<= r)
if(q[i] <= q[j]) temp[k++]=q[i++];
else temp[k++]=q[j++];
while(i <= mid) temp[k++ ]=q[i++ ];//若左半邊沒循環完 全部拿出來
while(j <= r) temp[k++ ] = q[j++ ];//若右半邊沒循環完 全部拿出來
for(i = l,j = 0;i <= r;i++,j++) q[i]=temp[j];//把temp排好的賦給q[]
}
int main()
{
cin>>n;
for(int i = 0;i < n; i++) cin>>q[i];
merge(q,0,n-1);//從0~n-1
for(int i = 0;i < n; i++) cout<<q[i]<<" ";
return 0;
}