归并排序

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移动   多用一个存储空间

优化
  1. 非递归
  2. 不回写   A->B->A(移动优化为 nlogn移动)
  3. 与插入结合(开始时可以16)
  4. 无逆序(从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;
   int i;
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++)
         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++)
         data[j]=data2[j];
     }    
      flag++;
    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];

}

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.....
  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++)
         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++)
         data[j]=data2[j];
     }    
      flag++;
    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;}
}
}

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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值