python - 无论条件如何,合并排序都会继续调用自身

标签 python recursion mergesort

我遇到了一个非常奇怪的问题,正在教自己写作。 我用 Python 进行了合并排序。

我想知道您是否可以帮助我理解为什么尽管满足关闭函数的条件,但它仍然继续调用自身。

print arrayToSort 
#[[67], [26], [75], [80], [54], [93], [97], [96], [77], [91]]

def merge_sort(array):
    newTotalArray = []
    for x in range(0, len(array)/2):
        newSubArray = []
        lowerX = x*2
        upperX = x*2+1
        while len(array[lowerX]) > 0 or len(array[upperX]) > 0:
            if len(array[lowerX]) > 0 and len(array[upperX]) > 0:
                if array[lowerX][0] <= array[upperX][0]:
                    newSubArray.append(array[lowerX][0])
                    del array[lowerX][0]
                else:
                    newSubArray.append(array[upperX][0])
                    del array[upperX][0]
            elif len(array[lowerX]) > 0:
                newSubArray.append(array[lowerX][0])
                del array[lowerX][0]
            else:
                newSubArray.append(array[upperX][0])
                del array[upperX][0]
        newTotalArray.append(newSubArray)
    if len(array) % 2 != 0:
        newTotalArray.append(array[len(array)-1])
    print 'still going'
    print newTotalArray
    if len(newTotalArray) > 1:
        merge_sort(newTotalArray)
    print 'finished'
    print newTotalArray

merge_sort(arrayToSort)

我希望这个函数在 len(newTotalArray) == 1 时停止调用自身。

但是,对于这段代码我得到了

[[67], [26], [75], [80], [54], [93], [97], [96], [77], [91]]
still going
[[26, 67], [75, 80], [54, 93], [96, 97], [77, 91]]
still going
[[26, 67, 75, 80], [54, 93, 96, 97], [77, 91]]
still going
[[26, 54, 67, 75, 80, 93, 96, 97], [77, 91]]
still going
[[26, 54, 67, 75, 77, 80, 91, 93, 96, 97]]
finished
[[26, 54, 67, 75, 77, 80, 91, 93, 96, 97]]
finished
[[], []]
finished
[[], [], []]
finished
[[], [], [], [], []]

我需要将其放入模块并返回结果,但如果这样做,结果是[[], [], [], [], []]

您能帮我理解为什么会发生这种情况吗?

最佳答案

问题在于 python 就地修改列表而不是列表的副本(这是按引用传递而不是按值传递)。因此,每次删除条目时,您都会将其从原始列表中删除,从而将您留下的条目删除。它并没有仍在调用,它只是在完成之前的值。额外的“空”数组来自末尾的 print 语句,而不是前面的数组。事实上,这些数组与提供的数组具有相同的长度,但都是空的,这告诉您此删除是在原始数组上发生的。

例如:

def mess_with_array(array):
    for i in range(2,len(array)):
        del array[2]

test = [1,2,3,4,5,6]
mess_with_array(test)
print test

结果为[1,2]。这是因为我们修改了原始数组。

诀窍是要么返回值(如果您不关心原始数组),要么使用副本并返回值。

改变

if len(newTotalArray) > 1:
    merge_sort(newTotalArray)

if len(newTotalArray) > 1:
    return merge_sort(newTotalArray)
else: return newTotalArray

并使用

运行该函数
arrayToSort = merge_sort(arrayToSort)

或者,如果您希望使用副本并保留原始数组,请使用

调用
sortedArray = merge_sort(arrayToSort[:])

这个按引用传递与按值传递的问题很微妙,如果你不小心的话,它会给你带来很大的麻烦。在处理一门新语言时,我首先关注的是它的传递方式。

一个额外的提示(以及我如何找出问题所在)。使用递归函数时,添加一个默认值为 0 的“calls”参数,并将其传递给每次递增 1 的函数,并在所有打印语句中提供它 - 这允许您查看每个调用来自哪些语句,让您看到该函数在最后展开。

关于python - 无论条件如何,合并排序都会继续调用自身,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34564350/

相关文章:

python - QGraphicsScene 和定位

python - 如何将提取的数据转换成python字典?

java - 循环计算整周并跳过天数

haskell - 我正在尝试重新定义 haskell 中的产品定义。我收到错误消息 "Non-exhaustive patterns in function"

erlang - 尾递归归并排序算法

保存在数据库中时的python datetime问题

Python:抓取整个字符串作为一个元素

每次递归都可以改成迭代吗?

java - 这部分代码会在归并排序中执行吗?

java - 合并排序 IllegalArgumentException