数据结构初阶——排序(Part3)(QuickSort)

目录

一、快排(递归版)改进 

1、背景

2、代码

二、快排(非递归版)

1、背景

2、思路

3、代码


一、快排(递归版)改进 

1、背景

在上一个 part 中我们留了个坑:

 就是随着快排递归深度的增加,数组就会越来越有序,那么就会降低快排的效率。而且,递归到最底层时需要排序的数组个数几乎占总体的一半。因此,为了解决这一问题,我们可以当数组长度到达某一个特定的值时,直接用插入排序对这个数组排序。

2、代码

void QuickSort(int* a, int left, int right)
{
	if (left >= right)
		return;
    
    /* 当长度小于10时,改用插入排序 */
	if (right - left + 1 < 10)
	{
		InsertSort(a + left, right - left + 1);
		return;
	}

	int ret = PartSort2(a, left, right);

	QuickSort(a, left, ret - 1);
	QuickSort(a, ret + 1, right);
}

二、快排(非递归版)

1、背景

由于有时递归次数过多会栈溢出,而非递归就不会,因此我们也要学会把递归的函数改成非递归的形式。

2、思路

因为快排的思想是先确定key最终的位置,然后再对左右部分进行子问题递归,因此这个过程与二叉树的前序遍历非常相似。再者,快排递归的过程就是一个建立栈帧销毁栈帧的过程,因此数据结构的栈毫无疑问是模拟函数栈帧的不二人选了。

由于在递归版的快排中,每个栈帧传的是数组的下标,因此在用栈模拟时,我们应该也把每次需要排序的下标区间存到栈里面。

3、代码

void QuickSortNonR(int* a, int left, int right)
{
	ST stack;
	STInit(&stack);

	/* 先放入待排序的区间 */
	STPush(&stack, right);
	STPush(&stack, left);

	/* 当栈为空时,整个快排就完成了 */
	while (!STEmpty(&stack))
	{
		int l = STTop(&stack);
		STPop(&stack);
		int r = STTop(&stack);
		STPop(&stack);

		/* 单趟快排 */
		int ret = PartSort3(a, l, r);

		if (r > ret + 1)
		{
			STPush(&stack, r);
			STPush(&stack, ret + 1);
		}

		if (l < ret - 1)
		{
			STPush(&stack, ret - 1);
			STPush(&stack, l);
		}

	}

	STDestroy(&stack);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胎粉仔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值