(C语言)快速排序的递归与非递归

1、原理 

(1)设定一个分界值key

(2)将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。

(3)左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理

2、递归实现

void QuickSort(int* a, int left, int right)
{
	if (left >= right)//递归结束条件
		return;

	int begin = left;
	int end = right;

	int key = left;//取最左边的值为基准值

	while (left < right)
	{
        //右边先走,遇到小于key的值时停止
		while (left < right && a[right] >= a[key])
			right--;

        //遇到大于key的值时停止
		while (left < right&& a[left] <= a[key])
			left++;

		Swap(&a[left], &a[right]);
	}
    //交换相遇位置与key
	Swap(&a[left], &a[key]);
    //key移动到了中间
	key = left;
    
    //begin      key      end
    //递归
	QuickSort(a, begin, key - 1);
	QuickSort(a, key + 1,end);

3.优化

当key最接近所有数据的中间值时,效率最高。而key太大或太小时,效率相对较低

这里采用三数取中的方法

//三数取中
//找出最左值,最右值,中间值中的mid
int GetMidNumi(int* a, int left, int right)
{
	int mid = (left + right) / 2;
	if (a[left] < a[mid])
	{
		if (a[mid] < a[right])
		{
			return mid;
		}
		else if (a[left] > a[right])
		{
			return left;
		}
		else
		{
			return right;
		}
	}
	else// a[left]>a[mid]
	{
		if (a[mid] > a[right])
		{
			return mid;
		}
		else if (a[left] < a[right])
		{
			return left;
		}
		else
		{
			return right;
		}
	}
}

void QuickSort1(int* a, int left, int right)
{
	if (left >= right)
		return;

	int begin = left;
	int end = right;

	//三数取中(找的是下标)
	int midi = GetMidNumi(a, left, right);
    if (midi != left)
		Swap(&a[midi], &a[left]);

	int key = left;
	while (left < right)
	{
		while (left < right && a[right] >= a[key])
			right--;

		while (left < right&& a[left] <= a[key])
			left++;

		Swap(&a[left], &a[right]);
	}
	Swap(&a[left], &a[key]);
	key = left;

	QuickSort1(a, begin, key - 1);
	QuickSort1(a, key + 1,end);

}

4.非递归实现

用栈实现(数字为数组元素下标)

将数字0和9入栈

将0和9出栈,先入栈6和9,再入栈0和4

出栈0和4,入栈3和4,再入栈0和1

 当区间只有一个值或者没有值时,不再入栈,,如此排序完所有区间

//需要栈的相关代码,这里就不给出了
// 快速排序 非递归实现
void QuickSortNonR(int* a, int left, int right)
{
    //栈的初始化
	ST st;
	STInit(&st);
    
    //入栈
	STPush(&st, right);
	STPush(&st, left);
    
    //当栈中无元素时就停止循环
	while (!STEmpty(&st))
	{
        
        //取栈顶元素
		int begin = STTop(&st);
        //出栈
		STPop(&st);
		int end = STTop(&st);
		STPop(&st);
        
        //单趟排序
		int key = QuickSort(a, begin, end);
		if (key + 1 < end)//判断是否需要继续入栈。下同
		{
			STPush(&st, end);
			STPush(&st, key + 1);
		}

		if (key > begin + 1)
		{
			STPush(&st, key-1);
			STPush(&st, begin);
		}
	}

	STDestroy(&st);

}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Saber_OvO

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

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

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

打赏作者

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

抵扣说明:

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

余额充值