5.2.6 三划分快速排序算法

本文介绍了一种改进的快速排序算法——三划分快速排序。通过将数组分为三个部分,该算法能够有效处理含有大量重复元素的情况,同时保持了传统快速排序的基本效率。文章详细解释了其实现逻辑,并提供了一个简洁高效的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

当数组中有大量重复的元素时用三划分可以有效地提升效率,并且当数组中没有大量重复元素时该算法的效率也不低于原快速排序的效率


思路

将整个数组分成三份,也就是找两个分界点,我们假设分界点l,r满足l<r,则中间有r−l个等于v的元素,左右分别为小于v和大于v的元素将整个数组分成三份,也就是找两个分界点,我们假设分界点l,r满足l<r,则中间有r-l个等于v的元素,左右分别为小于v和大于v的元素l,rl<r,rlvvv

根据这个逻辑,我们可以将等于v的元素分别放到pattern中数组的两端,最后把两端的数字转移到中央。因为根据快排的缘故,最终在中间的数字必然是左边小于v,右边大于v,只要各自把这两段交换一下即可。

为了快速写出正确高效的快排,之后pattern的方式均以下面的形式,这种形式优点是可以少写要交换时的两个指针的移动


实现

void QuickSort(Elem arr[], int l, int r) {
	if(l >= r) return ;
	int ltag, rtag, left, right;
	Elem v = arr[r];
	left = ltag = l - 1;
	right = rtag = r;
	while(1) {
		while(arr[++left] < v);
		while(arr[--right] > v) if(left == right) break;
		if(left >= right) break;
		swap(arr[left], arr[right]);
		if(arr[left] == v) {++ltag; swap(arr[left], arr[ltag]); } //当其相等后被拉到旁边,而旁边那个数之前已经验证必然<=v所以之后判++left的元素显然不会产生bug,右边同理
		if(arr[right] == v) {--rtag; swap(arr[right], arr[rtag]); }
	}
	swap(arr[left], arr[r]); //把标兵归为
	right = left + 1; left = left - 1; //相当于把标兵v左右区间和它相同的拉到中间

	for(int i = l; i < ltag; i++, left--) swap(arr[i], arr[left]);
	for(int i = r - 1; i > rtag; i--, right++) swap(arr[i], arr[right]);
	QuickSort(arr, l, left);
	QuickSort(arr, right, r);
}

主要的pattern:

	Elem v = arr[r];
	left = ltag = l - 1;
	right = rtag = r;
	while(1) {
		while(arr[++left] < v);
		while(arr[--right] > v) if(left == right) break;
		if(left >= right) break;
		swap(arr[left], arr[right]);
	}
	swap(arr[left], arr[r]);
	return left;
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小胡同的诗

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

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

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

打赏作者

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

抵扣说明:

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

余额充值