我试图了解QuickSelect分区的工作原理,但有一些我不了解的地方,我将尝试解释一下它的显示方式(请注意,我已将变量重命名并发表了评论,以尝试理解这一点,所以也许重命名或评论是错误的):
我见过各种不同的实现,而且我发现大多数(如果不是全部)都这样做。
// Partitioning.
private static int quickSelectPartition(int[] array, int left, int right, int pivotIndex) {
// The value of the pivot depends on the value at the random index that we got.
int pivotValue = array[pivotIndex];
// Move the pivot to the end.
swapLeftWithRight(array, pivotIndex, right);
// First pointer starts from left.
int firstPointer = left;
// Second pointer starts from left.
for(int secondPointer = left; secondPointer < right; secondPointer++) {
// If the value at the second pointer is less than pivot value, swap it to where the first pointer is.
if(array[secondPointer] < pivotValue) {
// Swap.
swapLeftWithRight(array, firstPointer, secondPointer);
// Move the first pointer forward.
firstPointer++;
}
}
// When done with this partitioning, swap the pivot back to its original position.
swapLeftWithRight(array, right, firstPointer);
return firstPointer;
}
答案 0 :(得分:0)
与合同有关。 quickSelectPartition
的协定(如果存在的话)会说类似“对数组进行排列并返回枢轴的新索引;枢轴之前的所有元素都小于枢轴,而枢轴之后的所有元素都大于或等于枢轴”。
此功能如何将其契约连接到循环不变式,将枢轴交换到末端,然后再返回到firstPointer
:“索引left..firstPointer-1
上的元素小于枢轴;索引处的元素firstPointer..secondPointer-1
大于或等于枢轴”。当secondPointer
为left
时,这个不变性成立。循环的目标是将secondPointer
增加到right
,同时保留不变性。我们可以将支点保留在这些数组的中间,但是要回答您的所有问题,不让支点不断跟随secondPointer
会更有效。
当然,还有其他方法可以处理分区,因此,您为什么要这么做的元答案是代码作者决定这样做的方式。