【数据结构与算法】快速排序的非递归实现方法

 

目录

一.前言

二.非递归实现


一.前言

如果数据量过大的话,不断递归就会出现栈溢出的现象,这个时候你的代码是没问题的,但就是跑不起来,这个时候就要把递归改成非递归

一般有两种改法:

1.直接改,利用循环等;

2.借助栈的辅助。

而快速排序的非递归实现方法就需要借助栈的辅助

二.非递归实现

通过观察我们发现,每次递归调用传过去的是一个数组和一个区间,数组自不用说,这个区间就是我们的突破点

也就是说我们只要想办法在循环的时候拿到本次要排序的区间就行了,那要怎么做呢?

借助数据结构:栈,栈具有后进先出的特性,借助这个就能很好的解决问题。

1.首先要先把 left 和 right 入栈,这样栈此时就不为空,然后开始循环。

2.取出栈顶的两个数据,分别赋给 begin 和 end ,注意在这之后要pop掉取出的数据

3.然后就是快排的逻辑,有三种方法,哪种都可以;

   如果不清楚这三种方法的话,请点击:快速排序的三种实现方法

   走完一趟后就得到了 keyi

4.然后数组就被 keyi 分成了两个子区间,分别是:

     左区间:[begin,keyi-1]

     右区间:[keyi+1,end]

 分别将左区间和右区间入栈,注意这里要判断:

       a.keyi+1<end

       b.keyi-1>begin

否则会出现数组访问越界或是死循环的情况。

5.因为栈是后进先出,所以要是想先排左区间的话,就要先入右区间进栈,反之;

6.循环结束后,销毁栈

void QuickSortNonR(Sdatatype* arr, int left, int right)
{
	ST st;
	Stackinit(&st);
	
	Stackpush(&st, right);
	Stackpush(&st, left);
	while (!Stackempty(&st))   //栈为空时就结束循环
	{
		int begin = Stacktop(&st);   //出一个就要pop掉一个数据
		Stackpop(&st);
		int end = Stacktop(&st);
		Stackpop(&st);
		int keyi = begin;    //以下为快速排序的逻辑,这里用的是前后指针法实现
		int mid = GetMid(arr, begin, end);
		if (mid != keyi)
			Swap(&arr[mid], &arr[keyi]);
		int prev = begin, cur = begin + 1;
		while (cur <= end)
		{
			if (arr[cur] < arr[keyi])
			{
				prev++;
				Swap(&arr[cur], &arr[prev]);
				cur++;
			}
			else
				cur++;
		}
		Swap(&arr[keyi], &arr[prev]);
		keyi = prev;   
		if (keyi + 1 < end)    //不要忘记判断
		{
			Stackpush(&st, end);    //这里是先入的右区间,所以是先排序左区间
			Stackpush(&st, keyi + 1);
		}
		if (keyi - 1 > begin)
		{
			Stackpush(&st, keyi - 1);
			Stackpush(&st, begin);
		}
	}

	Stackdestroy(&st);   //销毁栈
}

🐬🤖本篇文章到此就结束了,若有错误或是建议的话,欢迎小伙伴们指出;🕊️👻

😄😆希望小伙伴们能支持支持博主啊,你们的支持对我很重要哦;🥰🤩

😍😁谢谢你的阅读。😸😼

 

  • 38
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 36
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 36
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值