本文详解递归方法中递归调用位于方法体中部(非开头或结尾)时的执行流程,以 stars(int num) 为例,逐步剖析调用栈、回溯时机与输出行为,帮助掌握 AP CSA 考试中典型递归题型的分析逻辑。
本文详解递归方法中**递归调用位于方法体中部**(非开头或结尾)时的执行流程,以 `stars(int num)` 为例,逐步剖析调用栈、回溯时机与输出行为,帮助掌握 ap csa 考试中典型递归题型的分析逻辑。
在递归设计中,调用位置至关重要:递归调用若位于方法开头(头递归),常用于“先处理再递归”;若在结尾(尾递归),则易于优化且逻辑线性清晰;而当递归调用位于中间(如本例),则形成典型的“递推 → 暂停 → 回溯 → 执行剩余逻辑”模式。我们以 stars(5) 为例,逐层拆解其执行过程:
public static void stars(int num) {
if (num == 1) {
return; // 基准情况:直接返回,不打印
}
stars(num - 1); // ① 递归调用:暂停当前方法,进入更深层
for (int i = 0; i <h3>执行流程(栈视角)</h3>
- stars(5) → 检查 5 != 1 → 调用 stars(4),自身挂起(等待返回)
- stars(4) → 挂起 → stars(3)
- stars(3) → 挂起 → stars(2)
- stars(2) → 挂起 → stars(1)
- stars(1) → 触发 return,立即结束,不打印任何内容
此时调用栈开始逐层回溯:
- stars(1) 返回 → stars(2) 从 stars(1) 调用后继续执行 → 打印 **(2 个 *)+ 换行
- stars(2) 返回 → stars(3) 继续 → 打印 *** + 换行
- stars(3) 返回 → stars(4) 继续 → 打印 **** + 换行
- stars(4) 返回 → stars(5) 继续 → 打印 ***** + 换行
最终输出
** *** **** *****
注意:num == 1 时不输出,因此 stars(5) 共输出 4 行,行数为 num - 1,第 k 行(从上往下)含 k + 1 个 *(即 stars(k+1) 回溯时打印)。
关键要点总结
- ✅ 递归调用在中间 ≠ 死循环:只要基准条件正确(num == 1)且参数严格递减(num - 1),递归必终止。
- ✅ 所有“挂起”的方法只在回溯时执行后续代码:for 循环和 println() 不会在递推阶段运行,仅在返回途中触发。
- ⚠️ 易错点:误以为 stars(1) 会打印 * —— 实际它直接 return,这是输出从 ** 开始而非 * 的根本原因。
- ? 技巧:画调用栈图(标注每层 num 值和待执行语句位置),是分析此类问题最可靠的方法。
掌握这一模式,即可从容应对 AP CSA 中涉及“中置递归调用”的所有变体题目——核心永远是:递推建栈,回溯执行。











