两路归并排序算法

以下内容为程序代码:

#include <stdlib.h>
int mergesort(int p[], int n);
extern int insertsort(int p[], int n);
extern int stablesort(int p[], int n);
static int merge_sort(int p[], int swap[], int n, int count);
static int merge(int work[], int swap[], int m, int n, int flag);

/*
* 归并排序算法在 1938 年由 IBM 发明并在电动整理机上实现。
* 在 1945 年由 J. von Neumann 首次在 EDVAC 计算机上实现。
* 稳定,需要与序列同等大小的辅助空间。这里实现的是两路归并算法。
*/
#define IN 1
#define OUT 0

int mergesort(int p[], int n)
{
   int op=0;
   int * work=p;
   int * swap;
   int i,j,w;
   int count=0; /* 初始计数为偶数 */

   if (n<=16)
      return insertsort(work,n);
   swap=(int*)calloc(n,sizeof(int));
   if (swap==NULL)
      return 0;
   for(i=0;i+7<n;i+=8)
      op+=insertsort(work+i,8);
   if (i<n)
      op+=insertsort(work+i,n%8);
   for(i=8;i<n;i*=2) { /* i 为路段长度 */
      w=i*2; /* w 为路段长度乘以归并的路数 */
      for(j=0;j+w-1<n;j+=w)
         /* 平衡的两路归并 */
         op+=merge(work+j,swap+j,i,w,count);
      if (i+j<n)
         /* 不平衡的两路归并 */
         op+=merge(work+j,swap+j,i,n%w,count);
      else
         /* 换入或换出剩余的一个路段 */
         op+=merge(work+j,swap+j,n%w,n%w,count);
      count++; /* 计数增加 */
   }
   if (count%2) /*   计数为奇数 */
      for (i=0;i<n;i++)
         work=swap;
   free(swap);
   return op;
}

/*
* 两路归并过程。
*/
static int merge(int work[],   /* 工作空间,就是要归并的列表 */
       int swap[],   /* 交换空间,不小于工作空间 */
       int m,   /* 前半部分列表长度和后半部分列表的开始位置 */
       int n, /* 列表总长度 */
       int flag) /* 换入换出标志 */
{
   int *src, *dest;
   int i=0, j=m, t=0;

   flag%=2;
   if (flag==OUT) {
      src=work;
      dest=swap;
   }
   else { /* flag==IN */
      src=swap;
      dest=work;
   }
   while (i<m  && j<n) {
      if (src <= src[j]) {
         dest[t] = src;
         t++;
         i++;
      } else {
         dest[t] = src[j];
         t++;
         j++;
      }
   }
   while (i<m) {
      dest[t] = src;
      i = i++;
      t = t++;
   }
   while (j<n) {
      dest[t] = src[j];
      j++;
      t++;
   }
   return n;
}

/**************************************/
/*    下面是递归实现,留做参考        */
/**************************************/
int mergeSort(int p[], int n)
{
   int op=0;
   int * temp;

   if (n<=16)
      return insertsort(p,n);
   temp=(int*)calloc(n,sizeof(int));
   if (temp==NULL)
      return 0;
   op=merge_sort(p,temp,n,0);
   free(temp);
   return op;
}

static int merge_sort(int work[], int swap[], int n, int count)
{
   int op=0;
   int i, m;
   count++; /* 计数增加 */
   m=n/2;
   if(n<=8) {
      op+=insertsort(work,n);
      if (count%2==0) /* 计数为偶数 */
         for (i=0;i<n;i++)
            swap=work;
   } else {
      op+=merge_sort(work,swap,m,count);
      op+=merge_sort(work+m,swap+m,n-m,count);
      op+=merge(work,swap,m,n,count);
   }
   return op;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值