Bentley-McIlroy 三路分区

Sex*_*ast 1 python sorting algorithm partitioning quicksort

以下是Hoare我编写的基于给定主元对数组进行分区的分区算法(在这种情况下,它是数组的第一个元素,一个相当糟糕的选择!)。然而,Bentley-McIlroy 3-way partitioninghttp://www.sorting-algorithms.com/static/QuicksortIsOptimal.pdf声称提供更好的性能,当数字键是相等的。谁能简要解释一下第 9 页上的代码实现了什么,以及为什么它比Hoare算法执行得更好?还有一个问题,分区基于<,=和放置元素>。如果多次出现的元素不是枢轴怎么办?

def hoare(arr,start,end):
     pivot = arr[start]
     i,j = start,end
     while i < j:
        while i < j and arr[i] <= pivot:
            i += 1
        while j >= i and arr[j] > pivot:
            j -= 1
        if i < j:
            arr[i],arr[j] = arr[j],arr[i]
     arr[start],arr[j] = arr[j],arr[start]
     return j
Run Code Online (Sandbox Code Playgroud)

Lar*_*nyu 5

我发现可以根据N. Lumoto的想法实现3路分区,简单一点。(正如 Jon Bentley 在他的《编程珍珠》一书中提到的,Lumoto 的方法很简单)。

这个想法是在扫描期间保持不变,在任何时候,小于枢轴的元素都放在最左边的部分,而等于枢轴的元素放在该部分旁边,大于枢轴的元素枢轴放在最右边。其余部分是那些尚未检查的元素。

这些部分以 i、k 和 j 为界。当我们检查一个元素时,如果它等于主元,我们就前进到下一个元素,如果它小于主元,我们可以将它与'相等'部分的第一个元素交换,这样不变量就可以恢复了。否则,我们需要继续与较大部分前面的最后一个交换它。

/*
 * Another 3-way partition ternery quick sort based on N. Lomuto's method.
 *   Invariant: ... less ... | ... equal ... | ... ? ... | greater |
 *                           i               k           j
 */
void qsort3(Key* xs, int l, int u) {
    int i, j, k; Key pivot;
    if (l < u - 1) {
        i = l; j = u; pivot = xs[l];
        for (k = l + 1; k < j; ++k) {
            while (pivot < xs[k]) { --j; swap(xs[j], xs[k]); }
            if (xs[k] < pivot) { swap(xs[i], xs[k]); ++i; }
        }
        qsort3(xs, l, i);
        qsort3(xs, j, u);
    }
}
Run Code Online (Sandbox Code Playgroud)

我用 100,000 个元素针对标准库中的 qsort API 测试了这个程序。

  • Larry,我在一个 256*256 32 位整数数组上测试了这个 qsort3() 实现,并且排序的性能明显比 Bentley-mcilroy 实现差。我正在排序的数据包含大量重复值。 (2认同)