O(nlogn)
优化
与插入结合
优点在于有序列成倍增长
3 2 5 8 7 1 5 4
2 3 | 5 8 | 1 7 | 4 5
2 3 5 8 | 1 4 5 7
1 2 3 4 5 5 7 8
logn遍,每遍n比较 2nlogn移动 多用一个存储空间
优化
- 非递归
- 不回写 A->B->A(移动优化为 nlogn移动)
- 与插入结合(开始时可以16)
- 无逆序(从16以后最开始逆序出现开始)
弱点:需要空间 但空间只需关键字即可。
代码实现:
//这里用了非递归的方法,不回写data->data2->data
/**将a开头的长为length的数组和b开头长为right的数组合并n为数组长度,用于最后一组*/
void Merge(int* data,int *temp,int a,int b,int length,int n){
int right;
if(b+length>=n) right=n-b;
else right=length;
int i=0,j=0;
while(i<length&&j<right){
if(data[a+i]<=data[b+j]){
temp[a+i+j]=data[a+i];i++;}
else{temp[a+i+j]=data[b+j];j++;}
}
if(j==right)//a中还有元素,且全都比b中的大,a[i]还未使用
for(int k=0;k<length-i;k++)
temp[a+i+j+k]=data[a+i+k];
else
for(int k=0;k<right-j;k++)
temp[a+i+j+k]=data[b+j+k];
}
void MergeSort(int* data,int n){
int step=1;
int *data2=new int[n]
int flag=0;
void Merge(int* data,int *temp,int a,int b,int length,int n){
int right;
if(b+length>=n) right=n-b;
else right=length;
int i=0,j=0;
while(i<length&&j<right){
if(data[a+i]<=data[b+j]){
temp[a+i+j]=data[a+i];i++;}
else{temp[a+i+j]=data[b+j];j++;}
}
if(j==right)//a中还有元素,且全都比b中的大,a[i]还未使用
for(int k=0;k<length-i;k++)
temp[a+i+j+k]=data[a+i+k];
else
for(int k=0;k<right-j;k++)
temp[a+i+j+k]=data[b+j+k];
}
void MergeSort(int* data,int n){
int step=1;
int *data2=new int[n]
int flag=0;
int i;
while(step<n){
//将i和i+step这两个有序序列进行合并
//序列长度为step
//当i以后的长度小于或者等于step时,退出
if(flag%2==0)//data->data2->data.....
while(step<n){
//将i和i+step这两个有序序列进行合并
//序列长度为step
//当i以后的长度小于或者等于step时,退出
if(flag%2==0)//data->data2->data.....
{
for( i=0;i<n-step;i+=2*step)
Merge(data,data2,i,i+step,step,n);
for(int j=i;j<n;j++)
Merge(data,data2,i,i+step,step,n);
for(int j=i;j<n;j++)
data2[j]=data[j];
}
}
else
{
for( i=0;i<n-step;i+=2*step)
Merge(data2,data,i,i+step,step,n);
for(int j=i;j<n;j++)
Merge(data2,data,i,i+step,step,n);
for(int j=i;j<n;j++)
data[j]=data2[j];
}
flag++;
step*=2;//在按某一步长归并序列之后,步长加倍
}
if(flag%2==0)
step*=2;//在按某一步长归并序列之后,步长加倍
}
if(flag%2==0)
delete data2;
else
{
{
for( i=n;i<n;i++)
data[i]=data2[i];
delete data2;
}
}
}
代码基本不变将step初值赋为16,加入个插入排序代码。
void Merge(int* data,int *temp,int a,int b,int length,int n){
int right;
if(b+length>=n) right=n-b;
else right=length;
int i=0,j=0;
while(i<length&&j<right){
if(data[a+i]<=data[b+j]){
temp[a+i+j]=data[a+i];i++;}
else{temp[a+i+j]=data[b+j];j++;}
}
if(j==right)//a中还有元素,且全都比b中的大,a[i]还未使用
for(int k=0;k<length-i;k++)
temp[a+i+j+k]=data[a+i+k];
else
for(int k=0;k<right-j;k++)
temp[a+i+j+k]=data[b+j+k];
}
int right;
if(b+length>=n) right=n-b;
else right=length;
int i=0,j=0;
while(i<length&&j<right){
if(data[a+i]<=data[b+j]){
temp[a+i+j]=data[a+i];i++;}
else{temp[a+i+j]=data[b+j];j++;}
}
if(j==right)//a中还有元素,且全都比b中的大,a[i]还未使用
for(int k=0;k<length-i;k++)
temp[a+i+j+k]=data[a+i+k];
else
for(int k=0;k<right-j;k++)
temp[a+i+j+k]=data[b+j+k];
}
void MergeSort(int* data,int n){
int step=16;//改为16
int *data2=new int[n]
int flag=0;
while(step<n){
//将i和i+step这两个有序序列进行合并
//序列长度为step
//当i以后的长度小于或者等于step时,退出 if(flag%2==0)//data->data2->data.....
int step=16;//改为16
int *data2=new int[n]
int flag=0;
while(step<n){
//将i和i+step这两个有序序列进行合并
//序列长度为step
//当i以后的长度小于或者等于step时,退出 if(flag%2==0)//data->data2->data.....
if(flag%2==0)//data->data2->data.....
{
for( i=0;i<n-step;i+=2*step)
Merge(data,data2,i,i+step,step,n);
for(int j=i;j<n;j++)
Merge(data,data2,i,i+step,step,n);
for(int j=i;j<n;j++)
data2[j]=data[j];
}
}
else
{
for( i=0;i<n-step;i+=2*step)
Merge(data2,data,i,i+step,step,n);
for(int j=i;j<n;j++)
Merge(data2,data,i,i+step,step,n);
for(int j=i;j<n;j++)
data[j]=data2[j];
}
flag++;
step*=2;//在按某一步长归并序列之后,步长加倍
}
if(flag%2==0)
step*=2;//在按某一步长归并序列之后,步长加倍
}
if(flag%2==0)
delete data2;
else
{
{
for(i=n;i<n;i++)
data[i]=data2[i];
delete data2;
}
}
}
void insertion_sort(int array[],int first,int last)
{
int i,j;
int temp;
for(i=first+1;i<=last;i++)
{
temp=array[i];
j=i-1;
//与已排序的数逐一比较,大于temp时,该数移后
while((j>=0)&&(array[j]>temp))
{
array[j+1]=array[j];
j--;
}
//存在大于temp的数
if(j!=i-1)
{array[j+1]=temp;}
}
}
{
int i,j;
int temp;
for(i=first+1;i<=last;i++)
{
temp=array[i];
j=i-1;
//与已排序的数逐一比较,大于temp时,该数移后
while((j>=0)&&(array[j]>temp))
{
array[j+1]=array[j];
j--;
}
//存在大于temp的数
if(j!=i-1)
{array[j+1]=temp;}
}
}
void sort(int*data,int n)
{
int k;
for(int i=0;i<n;i+=16)
{
k=i+15;
if(k>n-1)
k=n-1;
insertion_sort(data,i,k);
}
MergeSort( data, n);
}