在Quicksort中进行分区之前,为什么pivot元素移动到数组的第一个或最后一个位置?

时间:2016-11-12 12:36:49

标签: algorithm sorting quicksort

我在某些地方读到,如果我们不选择第一个或最后一个元素作为枢轴,我们应该首先在分区开始之前将它与第一个或最后一个位置交换。所以我尝试了一个例子,我使用这个算法获得正确的分区https://www.cs.auckland.ac.nz/software/AlgAnim/qsort1a.html
该分区方法使用左指针和右指针。它将左指针移向中心,直到找到大于枢轴的元素。然后它将右指针移向中心,直到找到一个小于枢轴的元素。如果是右指针> leftpointer。交换这两个位置的值。最后,枢轴放置在右指针的位置。对于输入阵列12,18,17,11,13,15,16,14,选择元件15作为枢轴。
这些是步骤:
12,18,17,11,13,15,16,14

12,14,17,11,13,15,16,18(交换18和14)

12,14,13,11,17,15,16,18(交换17和13)

12,14,13,11,15,17,16,18(交换15和17)

1 个答案:

答案 0 :(得分:2)

Hoare partition scheme在概念上与问题中的示例类似,不同之处在于初始数据透视值可以从数组中的任何位置获取,并且不执行特殊的最终案例交换,作为数据透视值和在Hoare分区期间,枢轴指针将最终位于其正确的位置。

这是一个快速排序的例子,它使用3的中位数,Hoare分区方案,排除邻近和等于pivot的元素(它们已经被排序),并且只在较小的分区上使用递归来限制最坏情况下的堆栈空间为O(log(N))。

void QuickSort(uint32_t a[], size_t lo, size_t hi) {
    while(lo < hi){
        size_t i = lo, j = (lo+hi)/2, k = hi;
        uint32_t p;
        if (a[k] < a[i])            // median of 3
            std::swap(a[k], a[i]);
        if (a[j] < a[i])
            std::swap(a[j], a[i]);
        if (a[k] < a[j])
            std::swap(a[k], a[j]);
        p = a[j];
        i--;                        // Hoare partition
        k++;
        while (1) {
            while (a[++i] < p);
            while (a[--k] > p);
            if (i >= k)
                break;
            std::swap(a[i], a[k]);
        }
        i = k++;
        // at this point, a[i] or a[k] or both == p  (pivot value)
        while(i > lo && a[i] == p)  // exclude middle values == pivot
            i--;
        while(k < hi && a[k] == p)
            k++;
        // recurse on smaller part, loop on larger part
        if((i - lo) <= (hi - k)){
            QuickSort(a, lo, i);
            lo = k;
        } else {
            QuickSort(a, k, hi);
            hi = i;
        }
    }
}