递归调用栈可视化

递归一层层递出去,再一层层收回来——每一层就是一个栈帧。

CSP-JCSP-S

◎学完你会

1动一动:调用栈逐帧

int f(int n){ if(n<=1) return 1; // 出口 return n * f(n-1); // 先递归,再乘 }
调用 f(3) 的栈:[]
一层层压栈(递),到出口后一层层弹栈(归)。

2关键命令

要素说明例子
出口(基准情形)停止递归的条件n<=1
递(压栈)带更小参数调用自己f(n-1)
归(弹栈)返回后继续算n * 返回值
每次调用 f(n) 都压一个栈帧(存 n 和返回地址),到底后从最深一层逐层返回。f(3) = 3·f(2) = 3·2·f(1) = 3·2·1 = 6。

⚠易错点

忘记出口 → 栈溢出:没写 if(n<=1) return,递归永不停止,栈帧无限压,最终栈溢出崩溃(运行时 Error)。先写出口再写递归体。
递归太深也溢出:即使有出口,n 极大(如 1e6)也会压太深爆栈。深递归改用循环/递推(见 14.2)。

?跨学科:递归像“套娃”和“逐级上报”

小盒子里套大盒子再套更大……最里层算完,逐层向外返回结果。像逐级上报:你问你的上家,上家再问上家,问到最顶层拿到答案,再一层层传回来。

“把大问题拆成同型小问题,直到能直接答”是递归的核心,也是分治(14.3)的基石。

✎练一练

递归函数里“出口”(基准情形)的作用是?
出口是递归的终止条件:满足就直接返回,不再递归。没出口就会无限压栈、栈溢出崩溃。
递归函数忘记写出口,运行时会?
答案:栈溢出(无限递归,栈帧一直压到撑爆,程序崩溃)。任何递归都必须有能到达的基准情形。