排序-归并排序

归并排序是又一类不同的排序方法。归并的含义是将两个或两个以上的有序表组合成一个新的有序表。利用归并的思想容易实现排序。

算法思想:假设初始序列有n个记录,则可看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到n/2个长度为2或1的有序子序列,在两两归并,如此重复,直到得到一个长度为n的有序序列为止。这种排序方法称为2-路归并排序。

输入:顺序表的长度,顺序表中各个元素。

输出:排好序的顺序表中各个元素。

运行结果:

算法实现:

将相邻有序序列R[low..mid]和R[mid+1..high]归并为T[low..high]

void Merge(RedType R[],RedType T[],int low,int mid,int high)
{
    //将相邻有序序列R[low..mid]和R[mid+1..high]归并为T[low..high]
    int i=low,j=mid+1,k=low; //ijk各遍历一序列
    while(i<=mid&&j<=high)
    {
        //选择两子序列中当前小的填入T[k]
        if(R[i].key<=R[j].key)
	    RedCopy(T[k++],R[i++]);
	else
           RedCopy(T[k++],R[j++]);
    }
    while(i<=mid) //剩余段复制到T
        RedCopy(T[k++],R[i++]);
    while(j<=high)
        RedCopy(T[k++],R[j++]);
    for(i=low;i<=high;i++) //将合并完的T复制到R 以便下次归并时用
        RedCopy(R[i],T[i]);
}

归并排序算法实现(递归):

若序列长度为1直接填入T即可,否则将原序列一分为二,左右两侧子序列递归排序,最后调用归并函数进行归并。

将R[low..high]归并排序到T[low...high] 下标不变。

void MSort(RedType R[],RedType T[],int low,int high)
{
    /*归并排序
    若序列为1直接填入T即可,否则,将元序列一分为二,左右两侧子
    序列递归排序 最后调用归并函数进行归并 将R[low..high]归并排
    序到T[low..high] 下标不变*/
    int mid;
    if(low==high)
	RedCopy(T[low],R[low]);
    else
    {
        mid=(low+high)/2;
	MSort(R,T,low,mid); //递归排序到临时数组
        MSort(R,T,mid+1,high);
	Merge(R,T,low,mid,high); //归并到目标数组
    }
}

归并排序.

void MergeSort(SqList &L)
{
    //归并排序 递归实现
    RedType *T; //临时数组
    if(!(T=(RedType *)malloc((L.length+1)*sizeof(RedType))))
        exit(OVERFLOW);
    MSort(L.r,T,1,L.length);
    free(T);
    T=NULL;
}

算法分析:

时间复杂度:O(N*logN)

空间复杂度:O(N)

该算法是一种稳定的算法。

该算法还可以写成非递归的形式。

算法思想:将表中的相邻元素两两配对,用merge 对它们排序,构成n/2组长度为2的排好序的子区间段。然后将它们排序成长度为4的子区间段...如此重复啊重复,直到整个数组都排好序。

具体实现:

void Merge_Sort(SqList &L)
{
   /*归并排序 非递归实现
   将表中的相邻元素两两配对 用merge对他们排序 构成n/2组长度为2
   的排好序的子区间段,然后将他们排序成长度为4的子区间段,如此
   重复啊重复 直到整个数组排好序*/
   RedType *T; //临时数组
   if(!(T=(RedType *)malloc((L.length+1)*sizeof(RedType))))
       exit(OVERFLOW);
   int i,j,low,high,mid,pre_low,pre_high;
   for(i=2;i<=L.length;i*=2) //i为子区间长,2,4,.....
   {
       for(j=1;j<=L.length;j+=i) //对每一小块区间进行合并
       {
          low=j;
          high=j+i-1;
          mid=(low+high)/2;
	  if(high>L.length) //如果high越界 合并上一个区间与这个区间
	  {
	      low=pre_low; //修改low
	      mid=pre_high; //修改mid
              high=L.length;//修改high
	  }
          Merge(L.r,T,low,mid,high); //合并两个区间
	  pre_low=low; //保存上一个区间low
          pre_high=high;//保存上一个区间high
       }
   }
   free(T);
   T=NULL;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值