快速排序的深入优化(蒟蒻版三路划分)

快排性能的分析

决定快排性能的关键是每次单趟排序后,key对于数组的划分,如果key每次都能基本剧中二分,那么快排的递归树就是一棵均匀的满二叉树,性能也就最好。但是如果每次选的key都是最大值或者最小值那么每一次只能划分成0个跟n-1个子问题,时间复杂度就是 O(n^2)

,数组序列有序时就会出现这样的状况,可以使用三数取中或者随机选key解决这个问题,但是如果这个带排序的数组中有很多重复的数据,那么也是无法得到很好的解决的。

三路划分

当面对大量跟key值相等的值的时候,三路划分的核心思想有点类似hoare的左右指针跟lomuto前后指针的结合。核心思想就是把数组分成三段,1.比key小的值 2.跟key相等的值 3.比key大的值。

1.key默认取left位置的值

2.left指向数组的最左侧,right指向数组的最右侧。cur指向left的下一个。

3.判断cur指向的数据的值跟key比较

如果cur指向的值大于key,那么将cur指向的值跟right指向的值交换,然后right--;

如果cur指向的值小于key,那么将cur指向的值跟left指向的值交换,然后left++,cur++;

如果cur指向的值等于key,那么cur++;

这样可以保证我们cur左边的值一定先是跟key相等的值,left跟cur之间的都是跟key相等的值,再left左边都是比key小的值,在cur右边都是比key大的值。然后再递归左右两个区间

4.直到cur>right结束。

单趟之后:

下面是代码实现(带有备注的):

#define  _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
void swap(int* a, int* b)//这是交换函数
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
void myqsort(int* ch,int left, int right)//left代表最左边元素的数组下标,right代表最右边元素的数组下标
{
	if (left < right)
	{
		int Left = left;
		int Right = right;//记录位置
		int key = ch[left];
		int cur = left + 1;
		while (cur <= right)
		{
			if (ch[cur] > key)
			{
				swap(&ch[cur], &ch[right]);
				right--;
			}
			else if (ch[cur] < key)
			{
				swap(&ch[cur], &ch[left]);
				left++;
				cur++;
			}
			else
				cur++;
		}
		myqsort(ch, Left, left - 1);
		myqsort(ch, right + 1, Right);
	}
	else
		return;
}
int main()
{
	int ch[100010] = { 0 };
	int n = 0;
	scanf("%d", &n);
	for (int i = 0; i < n; i++)
		scanf("%d", &ch[i]);
	myqsort(ch, 0, n - 1);
	for (int i = 0; i < n; i++)
		printf("%d ", ch[i]);
	return 0;
}

这样优化好像无法通过洛谷上的排序,感兴趣的可以去试试:P1177 【模板】排序 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

这是leetcode上的排序链接:

. - 力扣(LeetCode)

还是很好理解的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值