快速 select 分区

Quick select partitioning

我试图了解 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;
}

一切都与合同有关。 quickSelectPartition 的合同,如果存在的话,会说类似 "permutes the array and returns the new index of the pivot; all elements before the pivot are less than the pivot, and all elements after the pivot are greater than or equal to the pivot".

的内容

将枢轴交换到末尾然后返回到 firstPointer 是此函数将其合同连接到循环不变量的方式:"the elements at indexes left..firstPointer-1 are less than the pivot; the elements at indexes firstPointer..secondPointer-1 are greater than or equal to the pivot"。当 secondPointerleft 时,此不变量平凡成立;循环的目标是将 secondPointer 增加到 right,同时保留不变量。我们可以将枢轴保持在这些数组的中间,但要回答您的所有问题,最好不要让枢轴不断移动以跟随 secondPointer.

当然还有其他处理分区的方法,所以对你的原因的元答案是代码作者决定这样做的方式。