就地归并排序算法的未做优化实现

以下内容为程序代码:

int imergesort(int p[], int n);

extern int insertsort(int p[], int n);
extern int appendsort(int p[], int m, int n);
extern int binarysearch(int p[],int n, int v, int *m);
static int exchange(int src[],int dest[],int n);
static int swapMergeSort(int p[], int swap[], int n, int count);
static int swapMerge(int work[], int swap[], int m, int n,int flag);
static int replaceMerge(int p[],int m, int q, int n);
#define IN 1
#define OUT 0

/*
* in-place 归并排序算法的始作俑者和优化实现请参见:
* http://www.diku.dk/hjemmesider/ansatte/jyrki/Experimentarium/
* 其优化的最终结果是“在理论上比高级版本的堆排序优越,在实际上
* 比常规的堆排序慢50%”。不稳定,不需要辅助空间。
* 余之实现意图说明标志性的方法而未做任何优化。
*/
int imergesort(int p[], int n)
{    
   int op=0;
   int i;
   int k=n; /* 在头部的未排序的元素数目 */
   int m=0; /* 在尾部的已排序的元素数目 */

   i=k/2;
   /* 用列表的前半部分做交换空间,
    * 对列表的后半部分做归并排序。*/
   op+=swapMergeSort(&p[n-i],p,i,0);
   m=m+i;
   k=k-i;
   while(k>4) {
      i=k/2;
      /* 用未排序子列表的后半部分做交换空间,
       * 对未排序子列表的前半部分做归并排序*/
      op+=swapMergeSort(p,&p,i,0);
      /* 把新排序出来的子列表与早先排序出来
       * 的子列表做不对称归并,它们之间的未
       * 排序空间被置换到列表头部。*/
      op+=replaceMerge(p,i,n-m,m);
      /* 列表的头部是未排序的,而尾部是已排序的 */
      m=m+i;
      k=k-i;
   }
   /* 最后的剩下的几个元素直接插入到已排序的列表中 */
   if(k<m)
      op+=appendsort(p,k,n);
   else /* 整个列表只有几个元素的时候 */
      op+=insertsort(p,n);

   return op; /* 返回操作数 */
}

/*
* 前提:0 -> m-1 和 q -> q+n-1 是两个有序列表,
* 中间从 m -> q-1 是大小为 q-m 的未排序的空间。
* 要求 q>=2*m,即中间的未排序空间大于等于左面的列表。
* 结果:归并出从 q-m 开始的大小是 m+n 的有序列表,
* 0 到 q-m-1 是被置换出来的大小是 q-m 的未排序的空间。
*/
static int replaceMerge(int p[],   /* 要归并的列表即左列表的头位置 */
         int m,   /* 左列表的长度 */
         int q,   /* 右列表的头位置 */
         int n)   /* 右列表的长度 */
{
   int op=0;
   int i=0,j=0,t=0;
   int w=n/m; /* 两个子列表大小的比 */
   int   r;
   int *left=p;
   int *right=&p[q];
   int *dest=&p[q-m];
   while (i<m && j<n) {
      /* 把左列表的一个元素与右列表的 w 个元素中的最大值做比较 */
      if (left>=right[j+w-1]) {
      /* 选择的左列表元素大于等于右列表的 m 个元素。*/
         op+=exchange(&right[j],&dest[t],w);
         t=t+w;
         j=j+w;
      }else{
      /* 以左列表一个元素作为查找值在右列表的 w 个元素中找到小于
       * 查找值的元素个数 */
         op+=binarysearch(&right[j],w,left,&r);
         if (r!=0) {
            op+=exchange(&right[j],&dest[t],r);
            t=t+r;
            j=j+r;
         }
         op+=exchange(&left,&dest[t],1);
         t++;
         i++;
      }
      if (w>n-j)
         w=n-j;
   }
   if (i<m)
      op+=exchange(&left,&dest[t],m-i);

   return op;
}
/*
* 交换过程,操作数是 2*n+1 而不是 3*n,但不保持目标列表的
* 原有次序,故只能用在有序列表与无序列表之间的交换。
*/
static int exchange(int src[],int dest[],int n)
{
   int i,temp;
   if (n==0)
      return 0;
   temp=dest[0];
   for(i=0;i<n-1;i++) {
      dest=src;
      src=dest[i+1];
   }
   dest=src;
   src=temp;
   return 2*n+1;
}

static int swapMergeSort(int work[], int swap[], int n, int count)
{
   int op=0;
   int m;
   count++;
   m=n/2;
   if(n<=8) {
      op+=insertsort(work,n);
      if (count%2==0)
         op+=exchange(work,swap,n);
   } else {
      op+=swapMergeSort(work,swap,m,count);
      op+=swapMergeSort(work+m,swap+m,n-m,count);
      op+=swapMerge(work,swap,m,n,count);
   }
   return op;
}

static int swapMerge(int work[], int swap[], int m, int n,   int flag)
{
   int *src, *dest;
   int i=0, j=m, t=0;
   int temp;

   flag%=2;
   if (flag==OUT) {
      src=work;
      dest=swap;
   }
   else { /* flag==IN */
      src=swap;
      dest=work;
   }

   temp=dest[t];
   while (i<m  && j<n) {
      if (src <= src[j]) {
         dest[t] = src;
         t++;
         src = dest[t];
         i++;
      } else {
         dest[t] = src[j];
         t++;
         src[j] = dest[t];
         j++;
      }
   }
   while (i<m) {
      dest[t] = src;
      t = t++;
      if (t<n)
         src = dest[t];
      else
         src = temp;
      i = i++;

   }
   while (j<n) {
      dest[t] = src[j];
      t++;
      if (t<n)
         src[j] = dest[t];
      else
         src[j] = temp;
      j++;
   }
   return 2*n+1;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值