非递归实现归并排序

我们常说,“没有最好,只有更好。”归并排序大量引用了递归,尽管在代码上比较清晰,容易理解,但这会造成时间和空间上的性能损耗。我们排序追求的就是效率,有没有可能将递归转化成迭代呢?结论当然是可以的,而且改动之后,性能上进一步提高了,来看代码。

/*  对顺序表L作归并非递归排序  */
void  MergeSort2(SqList  *L)
{
/*  申请额外空间  */
int  *  TR  =  (int  *)malloc(L->length  *  sizeof(int));        
int  k  =  1;
while  (k  <  L->length)
{
MergePass(L->r,  TR,  k,  L->length);
/*子序列长度加倍  */
k  =  2  *  k;              
MergePass(TR,  L->r,  k,  L->length);
/*  子序列长度加倍  */
k  =  2  *  k;              
}}

这段代码是归并排序算法的非递归实现。

首先,代码中通过malloc函数申请了一个大小为L->length的int类型数组TR,用来存放归并排序过程中的中间结果。

然后,通过一个while循环,不断进行归并排序的迭代。循环的条件是k小于L->length,其中k表示子序列的长度。

在循环内部,首先调用MergePass函数,将顺序表L中的元素归并排序到数组TR中,子序列的长度为k。MergePass函数的作用是将数组L->r中的元素按照长度为k的子序列进行归并排序,并将结果存放在数组TR中。

然后,将TR中的有序序列再次归并排序到顺序表L的r数组中,子序列的长度再次加倍。

通过不断迭代,每次将序列的子序列长度加倍,并在顺序表和临时数组之间进行归并排序,最终得到了完整的有序序列。

总结来说,这段代码实现了归并排序算法的非递归版本,通过迭代地将子序列的长度加倍,并在顺序表和临时数组之间进行归并排序,最终得到了完整的有序序列。

从代码中,我们能够感受到,非递归的迭代做法更加直截了当,从最小的序列开始归并直至完成。不需要像归并的递归算法一样,需要先拆分递归,再归并退出递归。
现在我们来看MergePass代码是如何实现的。

/*  将SR[]中相邻长度为s的子序列两两归并到TR[]  */
void  MergePass(int  SR[],  int  TR[],  int  s,  int  n)
{
int  i  =  1;
int  j;
while  (i  <=  n  -  2  *  s  +  1)
{
/*  两两归并  */
Merge(SR,  TR,  i,  i  +  s  -  1,  i  +  2  *  s  -  1);        
i  =  i  +  2  *  s;
}
/*  归并最后两个序列  */
if  (i  <  n  -  s  +  1)   
Merge(SR,  TR,  i,  i  +  s  -  1,  n);
/*  若最后只剩下单个子序列  */
else                        
for  (j  =  i;  j  <=  n;  j++)
TR[j]  =  SR[j];
}

这段代码是归并排序算法中的归并段落操作。

函数接收一个原始序列SR,一个用于存放结果的序列TR,以及两个参数s和n,表示对SR的相邻长度为s的子序列进行归并,归并结果存放在TR中,n表示SR中的元素个数。

首先,通过一个while循环,迭代地将SR中相邻长度为s的子序列两两归并到TR中。循环的条件是i小于等于n-2*s+1,其中i表示SR中子序列的起始位置。

在循环内部,调用Merge函数,将SR中的两个相邻子序列(起始位置分别为i和i+s-1,结束位置为i+2*s-1)归并到TR中。这样,每次循环都将两个相邻子序列归并到TR中。

每次循环后,更新i的值为i+2*s,继续处理下一对相邻子序列。

当循环结束时,如果i小于n-s+1,说明剩下的子序列长度大于s,即还有一对子序列需要归并。此时,再次调用Merge函数,将剩下的两个子序列归并到TR中。

如果i大于等于n-s+1,说明剩下的子序列长度小于等于s,即只有单个子序列未被归并。此时,通过一个循环将剩下的单个子序列复制到TR中。

通过这个归并段落操作,将SR中相邻长度为s的子序列逐步归并到TR中,生成更长的有序子序列。

综上所述,这段代码实现了归并排序算法的归并段落操作,通过迭代地将SR中相邻长度为s的子序列归并到TR中,最终得到更长的有序子序列。

非递归的迭代方法,避免了递归时深度为log2n的栈空间,空间只是用到申请归并临时用的TR数组,因此空间复杂度为O(n),并且避免递归也在时间性能上有一定的提升,应该说,使用归并排序时,尽量考虑用非递归方法。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值