歸併排序是一種分治策略。
將一串序列從中間分開,分爲low-mid,mid+1-high兩部分子序列。這是分解。
將子序列排序,並把排序後子序列重新複製給原數組。這是合併。
對子序列不斷遞歸調用,直到子序列個數爲1。數量爲1不再排序,直接將該數賦值給原數組。
例如一個序列 n=10
1 3 9 0 5 8 4 2 7 6
分解過程:1. 1-3-9-0-5 , 8-4-2-7-6
2. 1-3-9 , 0-5 ,8-4-2 ,7-6
3. 1-3 , 9 , 0 , 5 , 8-4 , 2 ,7 ,6
代碼:
#include <iostream>
using namespace std;
void Merge(int *p,int low,int mid,int high) //需要合併的數組,初始位置,中間位置,末尾位置
{
int *q = new int [high - low +1]; //申請輔助數組
int i=low,j=mid+1,k=0;
while(i<=mid && j<=high)
{
if(p[i] < p[j])
{
q[k] = p[i];
i++;
}
else
{
q[k] = p[j];
j++;
}
k++;
}
while(i<=mid)
{
q[k] = p[i];
i++,k++;
}
while(j<=high)
{
q[k] = p[j];
j++,k++;
}
for(i=low,k=0;i<=high;i++,k++)
p[i] = q[k];
}
void MergeSort(int *p,int low ,int high)
{
int mid;
if(low < high)
{
mid = (low + high)/2;
MergeSort(p,low,mid); //遞歸調用
MergeSort(p,mid+1,high);
Merge(p,low,mid,high);
}
}
int main()
{
int n,i;
cin>>n;
int p[n];
for(i=0;i<n;i++)
cin>>p[i];
MergeSort(p,0,n-1);
for(i=0;i<n;i++)
cout<<p[i]<<" ";
return 0;
}
時間複雜度的分析:
歸併排序的過程類似與構建一個二叉樹,對於具有N個數的序列,最終構成的二叉樹的的層數爲logN,自底向上解決時,每一層都要對這n個數排序一次,所以總的合併複雜度爲O(N*logN);
對於分解的複雜度,每一層的分解都是直接根據下標來分解,爲O(1),logN層就是 logN,最後總的時間複雜度還是O(N*logN)