快速排序中分区算法的延伸——划分多个区间

本文介绍了一种改进的分区算法,该算法能将数组划分为三个区间:小于、等于和大于主元的区间。通过设置两个索引并遍历数组,实现元素的有效交换。文章详细解释了算法的实现步骤,并提供了C++代码示例。

       按照自己的理解,分区算法partition的核心在于:索引的变换和交换元素,也就是说按照索引将不同的元素交换到不同的区间。快排中的partition只划分了2个区间:小等于以及大于。在这里,我们划分3个区间:小于、等于和大于,若给定数组arr{1,2,3,4,0,2},最后一个2设为主元nPivot,则经过分区后的数组也许为arr{1,0,2,2,4,3}(先不管相同区间的元素顺序)。

       划分3个区间的思路(以上面的数组为例):设2个索引值,分别指向0和第2个2,记为nBeforeEqual和nBeforeLarge,同时用i遍历整个数组。

       1.若arr[i] > nPivot,啥都不做。

       2.若arr[i] == nPivot,交换arr[nBeforeLarge+1]和arr[i],若数字序列为1,0,4,2,此时i指向2,nBeforeLarge指向0,则交换4和2即可,变成1,0,2,4。

       3.若arr[i] < nPivot, 先交换arr[nBeforeLarge+1]和arr[i],再交换arr[nBeforeLarge+1]和arr[nBeforeEqual+1],也就是说先把小元素交换到等于这个区间,再交换到小于这个区间,若数字序列为1,2,4,0,此时i指向0,nBeforeLarge指向2,nBeforeEqual指向1,先交换0和4,变成1,2,0,4,再交换2和0,变成1,0,2,4。

       最后,再交换arr[nBeforeEqual+1]和nPivot,把主元交换到等于区间,完成分区。


       代码如下:

<span style="font-size:24px;">template<typename T>
CNumPair partition(T* pArr, int nLeft, int nRight)
{
	int nPivot = pArr[nRight];
	int nBeforeEqual = nLeft-1;
	int nBeforeLarge = nLeft-1;

	for (int i = nLeft; i <= nRight; ++i)
	{
		if (pArr[i] < nPivot)
		{
			++nBeforeLarge;
			swap(pArr+nBeforeLarge, pArr+i);
			++nBeforeEqual;
			swap(pArr+nBeforeLarge, pArr+nBeforeEqual);
		}
		else if (pArr[i] == nPivot)
		{
			++nBeforeLarge;
			swap(pArr+nBeforeLarge, pArr+i);
		}
	}

	swap(pArr+nBeforeLarge+1, pArr+nRight);
	return CNumPair(nBeforeEqual+1, nBeforeLarge+1);
}</span>

同样,如果需要划分4个,5个区间,只需要多设几个索引值,每遍历一个元素,逐渐交换,一直换到对应的区间。

OVER


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值