我的mergesort实现有什么问题?

时间:2013-04-26 13:12:32

标签: python sorting recursion mergesort

在最小尺寸N = ~1950左右的较小列表上,我得到正确的输出......但是,不大得多的列表大小会返回错误而不是预期结果。我的代码:

def merge(left, right, aux=[]):
    if left == []:
        for x in right:
            aux.append(x)
        return aux
    elif right == []:
        for x in left:
            aux.append(x)
        return aux
    elif left[0] > right[0]:
        aux.append(right[0])
        return merge(left, right[1:], aux)
    else:
        aux.append(left[0])
        return merge(left[1:], right, aux)

def msort(values):
    size = len(values)

    if size == 1:
        return values
    else:
        mid = size/2
        return merge(msort(values[:mid]), msort(values[mid:]), [])

在这些测试列表上运行msort可以得到预期的(升序)输出:

val = [x for x in range(1950, 0, -1)
val = [x for x in range(4,0,-1)]

e.g。 [1,2,3,......,1948,1949,1950]和[1,2,3,4]

但是,当我在此测试用例上运行msort时:

val = [x for x in range(2000,0,-1)]

我现在收到此错误(经过多次追溯到merge):

RuntimeError: maximum recursion depth exceeded in cmp

所以我的问题是:我的实施在这里出了什么问题?我不能将它用于N~> = 2000的列表。为什么呢?

4 个答案:

答案 0 :(得分:4)

问题是你以递归方式进行合并。正如所指出的那样,可以调用merge(msort(left),msort(right)),但由于你的merge函数实际上会调用自己来进行合并,所以你会达到递归限制。

考虑在长度为1000的列表上调用merge函数。

要合并这些列表,您需要进行2000次合并调用(因为每次调用只需要向aux添加〜1个元素)。

答案 1 :(得分:2)

您的合并函数使用具有限制的递归。

如果你迭代而不是重复,你就绕过这个:

def merge(left, right, aux=[]):
    while left and right:
        if left[0] > right[0]:
            aux.append(right.pop(0))
        else:
            aux.append(left.pop(0))
    aux.extend(right)
    aux.extend(left)
    return aux

这是用法的一个例子:

>>> merge([1,3,5,7], [3,4,5,6])
[1, 3, 3, 4, 5, 5, 6, 7]

答案 2 :(得分:0)

您达到了最大递归深度。

这意味着,你的函数msort更经常地调用自己,而python默认允许这样做。

您可以使用sys.setrecursionlimit.

增加此默认值

答案 3 :(得分:0)

Python有递归限制。您可以使用以下方法设置最大值(小心):

import sys
sys.setrecursionlimit(MAXRECURSION)

我能够运行你的列表

val = [x for x in range(2000,0,-1)]

MAXRECURSION为2500