【发布时间】:2021-01-31 04:43:09
【问题描述】:
通常在实现快速排序时,Hoare 的方案比 Lomuto 的分区方案更有效,因为平均交换次数更少。为了验证这一点,我尝试用重复元素计算所有可能排列中的交换。我生成了一个包含 8 个元素的所有可能重复排列的列表来测试,总共是 8 个排列的 8 次方。但我机器上的结果很奇怪,Hoare 的方案即使交换次数较少,也较慢。这是python代码:
import copy
import time
swap_lomuto = 0
swap_hoare = 0
def hoare_partition(a, p, r):
global swap_hoare
pivot = a[(p+r)//2]
i = p - 1
j = r + 1
while True:
i = i + 1
j = j - 1
while a[i] < pivot:
i = i + 1
while a[j] > pivot:
j = j - 1
if i < j:
a[i], a[j] = a[j], a[i]
swap_hoare += 1
else:
return j
def quick_sort_hoare(a, lo, hi):
if lo < hi:
p = hoare_partition(a, lo, hi)
quick_sort_hoare(a, lo, p)
quick_sort_hoare(a, p+1, hi)
def lomuto_partition(a, p, r):
global swap_lomuto
pivot = a[r]
i = j = p
while j < r:
if a[j] < pivot:
a[i], a[j] = a[j], a[i]
i = i + 1
swap_lomuto += 1
j = j + 1
a[i], a[r] = a[r], a[i]
swap_lomuto +=1
return i
def quick_sort_lomuto(a, lo, hi):
if lo < hi:
p = lomuto_partition(a, lo, hi)
quick_sort_lomuto(a, lo, p-1)
quick_sort_lomuto(a, p+1, hi)
def gen_cases(n):
a = list(range(1, n+1))
r = [[]]
def product(A, B):
result = []
for a in A:
for b in B:
result.append(a + [b])
return result
for i in range(n):
r = product(r, a)
return r
# generate 8**8 permutations with repeated elements
# e.g. [[1, 1], [1, 2], [2, 1], [2, 2]] when n == 2
n = 8
cases1 = gen_cases(n)
cases2 = copy.deepcopy(cases1)
start = time.time()
for c in cases1:
quick_sort_lomuto(c, 0, len(c)-1)
end = time.time()
print("lomuto time: ", end-start)
print("lomuto swaps: ", swap_lomuto)
start = time.time()
for c in cases2:
quick_sort_hoare(c, 0, len(c)-1)
end = time.time()
print("hoare time: ", end-start)
print("hoare swaps: ", swap_hoare)
# assert if two methods give the same result
for i in range(len(cases1)):
for j in range(n):
assert cases1[i][j] == cases2[i][j]
我机器上的结果是
洛穆托时间:46.35845708847046
lomuto 掉期:199594736
暂停时间:59.4106240272522
霍尔掉期:116165488
我不知道哪里错了。
【问题讨论】: