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

来源:互联网 发布:淘宝客新建导购推广 编辑:程序博客网 时间:2024/06/06 14:16

       按照自己的理解,分区算法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


0 0
原创粉丝点击