我已经实现了一个快速排序算法来练习Python,这是我的代码:
def sort(array):
if len(array) > 1:
pivot = array[0]
left = []
right = []
equal = []
for x in array:
if x < pivot:
left.append(x)
elif x == pivot:
equal.append(x)
else:
right.append(x)
return sort(left)+equal+sort(right)
return array
现在,算法工作正常,但是如果我删除equal
列表并执行我的循环:
for x in array:
if x < pivot:
left.append(x)
else:
right.append(x)
return sort(left) + sort(right)
当我尝试对right
列表进行排序时,我得到了最大的递归深度错误。这不是因为该列表还包含相同的元素,我用非常小的列表测试它。我觉得这对我来说是一个非常愚蠢的错误,但到目前为止我找不到运气。
答案 0 :(得分:3)
看起来您可能不需要equal
列表,但它的存在至关重要。通过将那里的元素放入right
列表,您可以强制算法保留已排序的sort()
元素。这就是超出你的递归限制的原因。
通过在函数开头添加print "sorting", array
,您可以看到会发生什么:
>>> sort([3,1,2])
('sorting ', [3, 1, 2])
('sorting ', [1, 2])
('sorting ', [])
('sorting ', [1, 2])
('sorting ', [])
('sorting ', [1, 2])
('sorting ', [])
... etc. until crash
答案 1 :(得分:2)
枢轴总是作为第0个元素进入right
,并在right
递归时再次被选中。由于right
还包含等于或大于该值的所有内容,因此下一次调用会将当前元素的所有放入新的right
。
如果数据透视表是列表中唯一最大的项目,它将只会减少到一个元素 - 这最终意味着在任何其他情况下而不是您的列表没有重复项并且已经按降序排序命令,你将无限期地递归。
您不需要equal
列表,但是您确实需要至少从递归中选择所选的枢轴,因此下一次调用会选择另一个。所以选择这样:
pivot = array.pop(0)
并调整排序列表的重建:
return sort(left) + [pivot] + sort(right)