您的mergesort 函数会修改您传递给它的列表。也就是说,它会更改内容以使项目按顺序排列,而不是返回新列表。
这是您在递归调用期间在调试器中看到的内容。在递归的第一级中,lefthalf 是通过从原始列表中复制一些值来创建的(使用切片语法)。它开始包含[54, 26]。然后将该列表传递给mergesort 的另一个调用。请注意,命名可能会令人困惑,因为在内部调用中,它将列表称为alist(并且它有自己单独的lefthalf 列表)。当内部调用返回时,外部调用的lefthalf 的内容竟然被修改为[26, 54](它们是按顺序排列的,这就是我们想要的!)。
可能是您的调试器在返回发生时没有明确说明。由于都是同一个函数(由于递归),内部调用何时结束,外部调用的控制流恢复时可能并不明显。
这是您的代码演练,在您对示例列表进行排序时,我会在其中显示不同递归级别中不同变量的值。请注意,这不是可运行的 Python 代码,我正在缩进以指示递归级别,而不是用于控制流。为了使示例相对简短,我还省略了一些步骤,例如比较两个子列表中的值并在合并过程中更新 i j 和 k 索引:
plist = [54,26,93,17]
mergesort(plist)
# alist is a referece to plist which contains [54,26,93,17]
lefthalf = alist[:mid] # new list which initially contains [54,26]
righthalf = alist[mid:] # new list which initially contains [93,17]
mergesort(lefthalf)
# alist is a reference to the outer lefthalf list, which contains [54,26]
lefthalf = alist[:mid] # new list, initially contains [54]
righthalf = alist[mid:] # new list, initially contains [26]
mergesort(lefthalf)
# alist is a reference to the previous level's lefthalf, [54]
# the if statement doesn't pass its test, so we do nothing here (base case)
# lefthalf was not changed by the recursive call
mergesort(righthalf)
# alist is a reference to the previous level's righthalf, [26]
# base case again
# righthalf was not changed
alist[k]=righthalf[j] # now we merge lefthalf and righthalf back into alist
alist[k]=lefthalf[i] # these statements change the contents of alist
# lefthalf's contents changed, it is now sorted, [26,54]
mergesort(righthalf)
# alist is a reference to the outer righthalf list, which contains [93,17]
lefthalf = alist[:mid] # new list, initially contains [93]
righthalf = alist[mid:] # new list, initially contains [17]
mergesort(lefthalf) # base case, nothing happens (I'll skip the details)
mergesort(righthalf) # base case, nothing happens
alist[k]=righthalf[j] # merge lefthalf and righthalf back into alist
alist[k]=lefthalf[i] # we change the contents of alist to [17,93]
# righthalf's contents changed, it is now sorted, [17,93]
alist[k]=righthalf[j] # merge lefthalf and righthalf back into alist (more steps)
alist[k]=lefthalf[i]
alist[k]=lefthalf[i]
alist[k]=righthalf[j] # after these statements, alist is [17,26,54,93]
# plists's contents are changed so it contains [17,26,54,93]
这可能会帮助您从这种复杂的递归情况中退后一步,看看一个更简单的示例,以确保您了解列表是如何变异的:
a = [1, 2] # create a list object with some initial contents
b = a # b refers to the same list object as a, nothing is copied
b[1] = 3 # this modifies the list object itself, replacing the 2 with a 3
print(a) # prints [1, 3] even through we're looking at a rather than b
def func(lst): # lst will be a new name bound to whatever is passed to the function
lst[1] = 4 # we can modify that passed-in object (assuming it's the right type)
func(a) # lst in the function will become another name for the list object
print(a) # prints [1, 4]