最近我在python中比较了不同类型的排序算法。我注意到我的快速排序没有处理重复值的输入。
dragInteractionEnabled = true
然后我测试了这个
def compare_asc(a, b):
return a <= b
def partition(a, p, r, compare):
pivot = a[r]
i = p-1
for j in range(p, r):
if compare(a[j], 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 part_quick_sort(a, p, r, compare):
if p < r:
q = partition(a, p, r, compare)
part_quick_sort(a, p, q-1, compare)
part_quick_sort(a, q+1, r, compare)
def quick_sort(a, compare):
part_quick_sort(a, 0, len(a)-1, compare)
return a
在这个示例中,我得到import numpy as np
from timeit import default_timer as timer
import sys
test_list1 = np.random.randint(-10000, 10000, size=10000).tolist()
start = timer()
test_list1 = quick_sort(test_list1, compare_asc)
elapsed = timer() - start
print(elapsed)
test_list2 = np.random.randint(0, 2, size=10000).tolist()
start = timer()
test_list2 = quick_sort(test_list2, compare_asc)
elapsed = timer() - start
print(elapsed)
,所以我添加了RecursionError: maximum recursion depth exceeded in comparison
,之后我得到了这个输出:
sys.setrecursionlimit(1000000)
任何人都可以解释为什么它只在排序第二个列表时抛出这个递归深度错误?为什么会有这么大的时差?
答案 0 :(得分:3)
这里有一个提示:传递一个列表,其中所有元素都是相同的,并逐行观察它的作用。元素数量需要时间二次,并递归到大约等于元素数量的水平。
通常的快速分区实现从两端开始,因此在完全相同的情况下,列表切片大约被切成两半。在这种情况下,你可以获得不错的表现,只需从左到右看&#34;方法,但最明确的方法是划分为三个区域:&#34;小于&#34;,&#34;等于&#34;,&#34;大于&# 34。
这可以在一次从左到右的传递中完成,通常称为&#34; Dutch national flag problem&#34;。正如链接页面上的文字所示,
这个问题的解决方案对设计排序算法很感兴趣;特别是,必须对重复元素具有鲁棒性的快速排序算法的变体需要一个三向分区函数...
具体而言,这是一个完整的实施,一次通过&#34;从左到右&#34;单枢轴3路分区。它还包含了其他众所周知的变化,这些变化使得quicksort能够稳健地用于生产。注意:
O(N*log(N))
时间,并且(如下所示,一种方式)使最坏情况O(N**2)
时间不太可能。代码:
from random import randrange
def partition(a, lo, hi, pivot):
i = L = lo
R = hi
# invariants:
# a[lo:L] < pivot
# a[L:i] == pivot
# a[i:R] unknown
# a[R:hi] > pivot
while i < R:
elt = a[i]
if elt < pivot:
a[L], a[i] = elt, a[L]
L += 1
i += 1
elif elt > pivot:
R -= 1
a[R], a[i] = elt, a[R]
else:
i += 1
return L, R
def qsort(a, lo=0, hi=None):
if hi is None:
hi = len(a)
while True: # sort a[lo:hi] in place
if hi - lo <= 1:
return
# select pivot ar random; else it's easy to construct
# inputs that systematically require quadratic time
L, R = partition(a, lo, hi, a[randrange(lo, hi)])
# must recur on only the shorter chunk to guarantee
# worst-case recursion depth is logarithmic in hi-lo
if L - lo <= hi - R:
qsort(a, lo, L)
# loop to do qsort(a, R, hi)
lo = R
else:
qsort(a, R, hi)
# loop to do qsort(a, lo, L)
hi = L