简体   繁体   English

Quicksort超过最大递归深度

[英]Quicksort maximum recursion depth exceeded

I've implemented a quicksort algorithm to practice Python, here's my code: 我已经实现了一种快速排序算法来练习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

Now, the algorithm is working fine, but if I remove the equal list and do my loop like this: 现在,该算法运行良好,但是如果我删除了equal列表并执行如下循环:

    for x in array:
        if x < pivot:
            left.append(x)
        else:
            right.append(x)
    return sort(left) + sort(right)

I get the maximum recursion depth error when I try to sort the right list. 尝试对right列表进行排序时,出现最大递归深度错误。 It's not because that list also contains the equal elements, I tested it with very small lists. 并不是因为该列表也包含相等的元素,所以我用很小的列表对其进行了测试。 I'm feeling that this will be some really stupid mistake on my part, but I've had no luck in finding it so far. 我觉得这对我来说确实是一个愚蠢的错误,但是到目前为止我还没有运气。

It may look like you don't need the equal list, but its presence is critical. 看起来您不需要equal列表,但是它的存在至关重要。 By putting the elements that go there into the right list, you force the algorithm to keep sort() ing elements that are already sorted. 通过将要放在其中的元素放入right列表中,可以强制算法保留已排序的元素的sort()元素。 That's why your recursion limit is exceeded. 这就是为什么您的递归限制被超出的原因。

By adding a print "sorting", array at the start of your function, you can see what happens: 通过在函数开始处添加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

The pivot always goes into right as the zeroth element, and gets chosen again when you recurse on right . 枢轴总是进入right的零个元素,而当你在递归被再次选择right Since right also contains everything that is equal to or bigger than that, the next call will put all of the current elements into the new right . 由于right还包含等于或大于该值的所有内容,因此下一次调用会将所有当前元素放入新的right

It will only ever reduce to one element if the pivot is the unique largest item in the list - which ultimately means that in any other case than your list having no duplicates and already being sorted in descending order, you will recurse indefinitely. 如果支点是列表中最大的唯一项,则它将仅减少到一个元素-最终意味着,在列表没有重复且已经按照降序排序的其他情况下 ,您将无限期递归。

You don't need to have an equal list , but you do need to take at least the chosen pivot out of the recursion, so the next call down choses a different one. 您不需要具有equal 列表 ,但是您确实需要至少从递归中取出所选的枢轴,因此下一次调用将选择其他列表。 So choose it this way: 因此选择这种方式:

pivot = array.pop(0)

and adjust your reconstruction of the sorted list: 并调整您对已排序列表的重构:

return sort(left) + [pivot] + sort(right)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM