Lomuto的分区,稳定与否?

时间:2011-07-10 12:30:45

标签: algorithm sorting quicksort data-partitioning

我尝试在网络和算法手册中搜索 如果QSort分区的 Lomuto特定解决方案 稳定或不稳定(我知道Hoare的版本不稳定) 但我没有找到准确的答案 所以我试图做同样的例子,看起来很稳定。但我没有证明这一点。 你可以帮帮我吗? 如果它不稳定,你能找到我输入的例子吗?

2 个答案:

答案 0 :(得分:4)

我将解释“使用Lomuto分区的Quicksort”来指代here (slides 21–22)中的算法。

此算法在阵列[ a b c ]上不稳定,其中 c < a = b


我通过在Python中实现Quicksort算法找到了这个反例,这样(就像Python的内置排序一样)它需要一个key函数。通过提供适当的键功能,我可以认为某些元素是相同的,但我仍然可以区分它们。然后,这只是尝试大量排列和发现不稳定性的问题。下面的代码肯定不会耗尽可能的测试(人们可能想要尝试两个以上相同的元素,或多组相同的元素),但在这种情况下它已经足够了。

def testStability(f, n):
    """Try to discover if the sorting function f is stable on n inputs;
printing the first counterexample found, if any."""
    import itertools
    for i in range(n - 1):
        def order(P): return P.index((i, 0)) < P.index((i, 1))
        array = [(j, 0) for j in range(n - 1)] + [(i, 1)]
        for P in map(list, itertools.permutations(array)):
            Q = P[:] # take a copy
            f(Q, key=lambda x: x[0])
            if order(P) != order(Q):
                print P, '->', Q
                return

>>> testStability(lomuto, 3)
[(1, 0), (1, 1), (0, 0)] -> [(0, 0), (1, 1), (1, 0)]

答案 1 :(得分:0)

这取决于效率。

这是维基百科的伪代码。

algorithm quicksort(A, lo, hi) is
    if lo < hi then
        p := partition(A, lo, hi)
        quicksort(A, lo, p - 1)
        quicksort(A, p + 1, hi)

algorithm partition(A, lo, hi) is
    pivot := A[hi]
    i := lo
    for j := lo to hi do
        if A[j] < pivot then
            swap A[i] with A[j]
            i := i + 1
    swap A[i] with A[hi]
    return i

这是Java的实现。

    public static <E> void lomuto(final List<E> list, final Comparator<? super E> comparator) {
        LOMUTO_SWAP_COUNTER.remove();
        LOMUTO_SWAP_COUNTER.set(new LongAdder());
        sort(list,
             comparator,
             (l, c) -> {
                 assert !l.isEmpty();
                 final int p = l.size() - 1;
                 int i = 0;
                 for (int j = 0; j < l.size() - 1; j++) {
                     if (c.compare(l.get(j), l.get(p)) < 0) { // < vs <=
                         swap(l, j, i++);
                         LOMUTO_SWAP_COUNTER.get().increment();
                     }
                 }
                 swap(l, p, i);
                 return i;
             });
    }

具有以下数据,

[Three(3), John(2), Jane(2), One(1)] // original unsorted

以上实现与不稳定输出交换2次。

[One(1), Jane(2), John(2), Three(3)] // unstable, with 2 swaps

当您将c.compare(l.get(j), l.get(p)) < 0更改为c.compare(l.get(j), l.get(p)) <= 0时,

该实现会交换3次,并获得稳定的输出。

[One(1), John(2), Jane(2), Three(3)] // stable, with 3 swaps