You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

递归实现归并排序的执行流程疑问及示例解析请求

归并排序递归实现的底层细节解析

问题概述

我希望深入理解递归实现的归并排序算法的底层执行细节,但对这段mergeSort函数存在疑问:

  1. 该函数的基例(base case)是什么?
  2. 递归调用到达基例(如处理单元素数组)时,为何没有返回值?
    此外,我以数组[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:递归拆分(从原数组不断拆分为更小的子数组)

  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)。
  2. 处理L=[4,2,7,9],长度4>1:
    • mid=2,拆分出L1=[4,2],R1=[7,9],递归调用mergeSort(L1)。
  3. 处理L1=[4,2],长度2>1:
    • mid=1,拆分出L2=[4],R2=[2],递归调用mergeSort(L2)。
    • L2长度为1,触发基例,直接结束。
  4. 调用mergeSort(R2=[2]),长度为1,触发基例,直接结束。
  5. 回到L1的合并逻辑:将有序的L2=[4]和R2=[2]合并,L1被修改为[2,4]。
  6. 调用mergeSort(R1=[7,9]),长度2>1:
    • 拆分出L3=[7],R3=[9],递归调用后均触发基例结束。
    • 合并L3和R3,R1被修改为[7,9]。
  7. 回到L的合并逻辑:将有序的L1=[2,4]和R1=[7,9]合并,L被修改为[2,4,7,9]。
  8. 回到初始调用,递归调用mergeSort(R=[12,3,1,5]):
    • mid=2,拆分出L4=[12,3],R4=[1,5],递归调用mergeSort(L4)。
  9. 处理L4=[12,3],长度2>1:
    • 拆分出L5=[12],R5=[3],递归调用后均触发基例结束。
    • 合并L5和R5,L4被修改为[3,12]。
  10. 调用mergeSort(R4=[1,5]),长度2>1:
    • 拆分出L6=[1],R6=[5],递归调用后均触发基例结束。
    • 合并L6和R6,R4被修改为[1,5]。
  11. 回到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
  • 此时i已等于len(L),退出循环,将R中剩余的12放入arr[7]。
  • 最终原数组被修改为[1,2,3,4,5,7,9,12],排序完成。

内容的提问来源于stack exchange,提问作者Solruhama

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 20:31:04