Python递归归并排序代码疑问:未赋值为何lefthalf变量会改变
为啥无返回值的mergeSort能修改lefthalf?
哈哈,这个问题戳中了Python中可变对象的核心特性!咱们结合你的代码一步步捋清楚:
首先先补全你没写完的归并排序完整逻辑(毕竟merge阶段是关键):
def merge(alist, lefthalf, righthalf): i = j = k = 0 # 合并两个有序子列表到alist中 while i < len(lefthalf) and j < len(righthalf): if lefthalf[i] < righthalf[j]: alist[k] = lefthalf[i] i += 1 else: alist[k] = righthalf[j] j += 1 k += 1 # 处理剩余元素 while i < len(lefthalf): alist[k] = lefthalf[i] i += 1 k += 1 while j < len(righthalf): alist[k] = righthalf[j] j += 1 k += 1 def mergeSort(alist): print("Splitting ",alist) if len(alist)>1: mid = len(alist)//2 lefthalf = alist[:mid] righthalf = alist[mid:] print("Before left call------>",lefthalf) mergeSort(lefthalf) print("after left call------>",lefthalf) mergeSort(righthalf) merge(alist,lefthalf,righthalf)
核心原因:Python列表是可变对象
在Python中,列表属于可变(mutable)对象,当你把列表作为参数传给函数时,传递的是对象的引用(不是列表的副本)。这意味着:
- 函数内部对这个列表的直接修改,会直接作用于内存中的原列表对象
- 哪怕函数没有返回值,外部的变量(比如这里的lefthalf)指向的还是同一个内存对象,所以能看到修改后的结果
具体到你的代码流程
假设初始lefthalf是[54,26]:
- 调用
mergeSort(lefthalf),递归拆分到子列表[54]和[26](长度为1,不再拆分) - 进入merge阶段:递归返回时,会调用
merge函数,把传入的alist(也就是当前递归层的lefthalf)替换成合并后的有序列表[26,54] - 当递归回到上层时,原来的lefthalf变量指向的还是同一个列表对象,所以它的值已经变成了排序后的结果
对比理解:不可变对象的差异
如果是整数、字符串这类不可变对象,函数内部修改只会创建新对象,不会影响外部变量。比如:
def add_one(num): num += 1 a = 5 add_one(a) print(a) # 输出还是5,因为整数不可变,函数里的num是新对象
而列表这种可变对象,函数操作的是原对象的引用,所以修改会直接生效~
内容的提问来源于stack exchange,提问作者jasmin
相关产品推荐
相关产品推荐

