递归实现归并排序的执行流程疑问及示例解析请求
归并排序递归实现的底层细节解析
问题概述
我希望深入理解递归实现的归并排序算法的底层执行细节,但对这段mergeSort函数存在疑问:
- 该函数的基例(base case)是什么?
- 递归调用到达基例(如处理单元素数组)时,为何没有返回值?
此外,我以数组[4,2,7,9,12,3,1,5]为例阐述了对执行流程的错误理解,请求结合该示例详细讲解递归执行的完整步骤。
附函数代码
def mergeSort(arr): if len(arr) > 1: mid = len(arr)//2 print("This is funny", arr, arr[0], len(arr)) L = arr[:mid] R = arr[mid:] mergeSort(L) mergeSort(R) i = j = k = 0 while i < len(L) and j < len(R): if L[i] < R[j]: arr[k] = L[i] i += 1 else: arr[k] = R[j] j += 1 k += 1 # 检查是否有剩余元素未处理 while i < len(L): arr[k] = L[i] i += 1 k += 1 while j < len(R): arr[k] = R[j] j += 1 k += 1
疑问解答
1. 函数的基例是什么?
这段代码的基例是当输入数组的长度≤1时:此时函数不会进入if len(arr) > 1的代码块,直接执行结束。因为单元素数组本身就是有序的,不需要任何拆分或合并操作。
2. 基例为何没有返回值?
因为这个mergeSort函数采用原地修改数组的设计:
- 递归调用处理子数组
L和R时,会直接把L和R内部排序好(修改传入的子数组本身)。 - 上层函数不需要等待返回值,直接使用已经被排序后的
L和R,将它们合并到原数组arr的对应位置即可。 - 整个排序过程中,所有修改都是直接作用于传入的数组对象,因此不需要返回新数组,基例自然也无需返回值。
示例数组[4,2,7,9,12,3,1,5]的完整执行流程
我们把执行过程拆分为递归拆分和合并排序两个阶段,结合代码逻辑一步步解析:
阶段1:递归拆分(从原数组不断拆分为更小的子数组)
- 初始调用
mergeSort([4,2,7,9,12,3,1,5]),长度8>1:- 计算
mid=4,拆分出L=[4,2,7,9],R=[12,3,1,5],先递归调用mergeSort(L)。
- 计算
- 处理
L=[4,2,7,9],长度4>1:mid=2,拆分出L1=[4,2],R1=[7,9],递归调用mergeSort(L1)。
- 处理
L1=[4,2],长度2>1:mid=1,拆分出L2=[4],R2=[2],递归调用mergeSort(L2)。L2长度为1,触发基例,直接结束。
- 调用
mergeSort(R2=[2]),长度为1,触发基例,直接结束。 - 回到
L1的合并逻辑:将有序的L2=[4]和R2=[2]合并,L1被修改为[2,4]。 - 调用
mergeSort(R1=[7,9]),长度2>1:- 拆分出
L3=[7],R3=[9],递归调用后均触发基例结束。 - 合并
L3和R3,R1被修改为[7,9]。
- 拆分出
- 回到
L的合并逻辑:将有序的L1=[2,4]和R1=[7,9]合并,L被修改为[2,4,7,9]。 - 回到初始调用,递归调用
mergeSort(R=[12,3,1,5]):mid=2,拆分出L4=[12,3],R4=[1,5],递归调用mergeSort(L4)。
- 处理
L4=[12,3],长度2>1:- 拆分出
L5=[12],R5=[3],递归调用后均触发基例结束。 - 合并
L5和R5,L4被修改为[3,12]。
- 拆分出
- 调用
mergeSort(R4=[1,5]),长度2>1:- 拆分出
L6=[1],R6=[5],递归调用后均触发基例结束。 - 合并
L6和R6,R4被修改为[1,5]。
- 拆分出
- 回到
R的合并逻辑:将有序的L4=[3,12]和R4=[1,5]合并,R被修改为[1,3,5,12]。
阶段2:最终合并(将两个有序子数组合并为原数组)
回到初始调用的合并逻辑,将已经排序好的L=[2,4,7,9]和R=[1,3,5,12]合并到原数组:
- 初始化
i=j=k=0,循环比较L[i]和R[j],将较小值放入arr[k],逐步移动指针:- 1<2 →
arr[0]=1,j=1,k=1 - 2<3 →
arr[1]=2,i=1,k=2 - 3<4 →
arr[2]=3,j=2,k=3 - 4<5 →
arr[3]=4,i=2,k=4 - 5<7 →
arr[4]=5,j=3,k=5 - 7<12 →
arr[5]=7,i=3,k=6 - 9<12 →
arr[6]=9,i=4,k=7
- 1<2 →
- 此时
i已等于len(L),退出循环,将R中剩余的12放入arr[7]。 - 最终原数组被修改为
[1,2,3,4,5,7,9,12],排序完成。
内容的提问来源于stack exchange,提问作者Solruhama
相关产品推荐
相关产品推荐

