我尝试在 Web 和我的算法书中搜索Lomuto 的QSort 分区的特定解决方案是否稳定(我知道 Hoare 的版本不稳定)但我没有找到准确的答案。
所以我试着做同样的例子,它看起来很稳定。但我没有演示。你可以帮帮我吗?如果它不稳定,你能给我找一个输入的例子吗?
问问题
3307 次
2 回答
8
我将把“使用 Lomuto 分区的快速排序”解释为引用此处的算法(幻灯片 21–22)。
该算法在数组 [ a , b , c ] 上不稳定,其中c < a = b。
我通过在 Python 中实现快速排序算法找到了这个反例,这样(就像 Python 的内置排序一样)它需要一个key
函数。通过提供适当的键功能,我可以使排序认为某些元素是相同的,但我仍然可以区分它们。然后,只需尝试大量排列并发现不稳定性。下面的代码当然没有穷尽可能的测试(人们可能想尝试两个以上相同的元素,或多组相同的元素),但在这种情况下已经足够好了。
def lomuto(A, key=lambda x:x):
def partition(A, p, r):
i = p - 1
pivot = A[r]
for j in range(p, r):
if key(A[j]) <= key(pivot):
i += 1
A[i], A[j] = A[j], A[i]
A[i+1], A[r] = A[r], A[i+1]
return i + 1
def quicksort(A, p, r):
if p < r:
q = partition(A, p, r)
quicksort(A, p, q-1)
quicksort(A, q+1, r)
quicksort(A, 0, len(A) - 1)
def test_stability(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
>>> test_stability(lomuto, 3)
[(1, 0), (1, 1), (0, 0)] -> [(0, 0), (1, 1), (1, 0)]
于 2011-07-10T13:37:09.240 回答
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
于 2020-01-15T04:55:54.863 回答