快速选择分区

时间:2018-11-10 19:24:35

标签: java algorithm big-o quicksort quickselect

我试图了解QuickSelect分区的工作原理,但有一些我不了解的地方,我将尝试解释一下它的显示方式(请注意,我已将变量重命名并发表了评论,以尝试理解这一点,所以也许重命名或评论是错误的):

  • 首先,数据透视表的值就是数据透视表所在的索引的值。
  • 我们现在将枢轴交换到数组的末尾,为什么?
  • 我们有一个从左开始的第一个指针,因为第一个指针当然应该从头开始。
  • 在for循环中,我们还有第二个指针,它也从左侧开始,为什么?。它不应该从另一端开始吗?
  • 如果我们的位置小于枢轴值,请交换它们,以便将较小的元素移到左侧。
  • 最后交换枢轴向后(这导致我的拳头“为什么”)。
  • 最后,我们返回第一个指针,我认为这是因为那是数组中剩下的唯一元素了吗?

我见过各种不同的实现,而且我发现大多数(如果不是全部)都这样做。

// 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;
}

1 个答案:

答案 0 :(得分:0)

与合同有关。 quickSelectPartition的协定(如果存在的话)会说类似“对数组进行排列并返回枢轴的新索引;枢轴之前的所有元素都小于枢轴,而枢轴之后的所有元素都大于或等于枢轴”。

此功能如何将其契约连接到循环不变式,将枢轴交换到末端,然后再返回到firstPointer:“索引left..firstPointer-1上的元素小于枢轴;索引处的元素firstPointer..secondPointer-1大于或等于枢轴”。当secondPointerleft时,这个不变性成立。循环的目标是将secondPointer增加到right,同时保留不变性。我们可以将支点保留在这些数组的中间,但是要回答您的所有问题,不让支点不断跟随secondPointer会更有效。

当然,还有其他方法可以处理分区,因此,您为什么要这么做的元答案是代码作者决定这样做的方式。