归并排序是一种分治策略。
将一串序列从中间分开,分为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)