算法思想描述:
要对一个数组排序,可以将它先分为两个子数组分别排序,最后将结果合并。
下面介绍两种排序:自顶向下的归并排序和自底向上的归并排序。
1:自顶向下的归并排序
对一个数组排序先将左子数组排序,右子数组排序,最后合并形成最后的有序的数组,要对左子数组进行排序,采用同样的方式分割数组······
以整数数组为例:
#include <iostream>
#include <math.h>
using namespace std;
const int Num=25;
int Mid[Num]={0};
void Merge(int* s,int low,int mid,int up)
{
int a=low,b=mid+1;
for(int i=low;i<=up;i++)
Mid[i]=s[i];
for(int i=low;i<=up;i++)
{
if(a>mid)
s[i]=Mid[b++];
else if(b>up)
s[i]=Mid[a++];
else if(Mid[a]<=Mid[b])
s[i]=Mid[a++];
else s[i]=Mid[b++];
}
}
int Sort(int* s,int low,int up)//归并排序
{
if(up<=low)
return 0;
else
{
int mid=(low+up)/2;
Sort(s,low,mid);
Sort(s,mid+1,up);
Merge(s,low,mid,up);
}
}
int main()
{
int array[Num];
srand(7);//初始化随机数
for(int i=0;i<Num;i++)//初始化数组0到100之间
{
array[i]=rand() % 101;
}
for(int i=0;i<Num;i++)//输出原数组
{
printf("%d ",array[i]);
}
Sort(array,0,Num-1);
printf("\n");
for(int i=0;i<Num;i++)
{
printf("%d ",array[i]);
}
return 0;
}
2:自底向上的归并排序(非递归)
先归并那些微型数组,然后再成对归并得到子数组。
#include <iostream>
#include <math.h>
using namespace std;
const int Num=25;
int Mid[Num]={0};
void Merge(int* s,int low,int mid,int up)
{
int a=low,b=mid+1;
for(int i=low;i<=up;i++)
Mid[i]=s[i];
for(int i=low;i<=up;i++)
{
if(a>mid)
s[i]=Mid[b++];
else if(b>up)
s[i]=Mid[a++];
else if(Mid[a]<=Mid[b])
s[i]=Mid[a++];
else s[i]=Mid[b++];
}
}
int Sort(int* s)//归并排序
{
for(int i=1;i<Num;i=i+i)
{
for(int j=0;j<Num-i;j+=i+i)
Merge(s,j,j+i-1,(j+i+i-1)<(Num-1)?(j+i+i-1):(Num-1));
}
}
int main()
{
int array[Num];
srand(7);//初始化随机数
for(int i=0;i<Num;i++)//初始化数组0到100之间
{
array[i]=rand() % 101;
}
for(int i=0;i<Num;i++)//输出原数组
{
printf("%d ",array[i]);
}
Sort(array);
printf("\n");
for(int i=0;i<Num;i++)
{
printf("%d ",array[i]);
}
return 0;
}
一个规模为N的数组,归并排序所需时间和NlgN成正比。相对于其他排序算法已经很优了,但是辅助数组的使用额外空间和N成正比。
改进 :
1:对于小规模数组使用插入排序算法。
2:Merge时先判断如果array[mid]<=array[mid+1]则数组已经有序,不用Merge().
3:不将元素复制到辅助数组。(采用其他方式,此处不详细展开)