C++ 递归算法实战:汉诺塔问题详解
核心思路
汉诺塔是递归思想的经典案例。解决这个问题的关键在于将大规模问题拆解为小规模子问题。
假设我们有三根柱子 A、B、C,初始时 A 柱上有 n 个盘子(从小到大叠放),目标是将所有盘子移动到 C 柱,且移动过程中大盘子不能压在小盘子上面。
我们可以这样思考:
- 当 n = 1 时:直接将 A 上的盘子移到 C 即可。
- 当 n > 1 时:
- 先将 A 上面的 n-1 个盘子借助 C 移动到 B;
- 将 A 上剩下的最大盘子直接移到 C;
- 最后将 B 上的 n-1 个盘子借助 A 移到 C。
通过这种'分而治之'的策略,无论盘子数量多少,最终都能转化为 n=1 的基础情况完成移动。
算法流程设计
我们需要一个递归函数来模拟上述过程。函数签名可以设计为 dfs(vector<int>& A, vector<int>& B, vector<int>& C, int n),其中 A、B、C 分别代表三个柱子,n 表示当前需要移动的盘子数量。
具体执行逻辑如下:
- 终止条件:如果 n == 1,直接将 A 栈顶元素弹出并压入 C 栈,返回。
- 递归步骤:
- 调用
dfs(A, C, B, n-1),将 A 的前 n-1 个盘子移到辅助柱 B。 - 将 A 的剩余最大盘子移到目标柱 C。
- 调用
dfs(B, A, C, n-1),将 B 上的 n-1 个盘子移到目标柱 C。
- 调用
这里要注意参数顺序的变化。在第一次递归中,C 充当了辅助角色;在第二次递归中,A 变成了辅助角色。理解这一点对于正确实现代码至关重要。
代码实现
下面给出完整的 C++ 实现。为了便于调试和理解,我在关键位置添加了注释。
class Solution {
public:
// 深度优先搜索辅助函数
// A: 源柱子,B: 辅助柱子,C: 目标柱子,n: 待移动盘子数
void dfs(vector<int>& A, vector<int>& B, vector<int>& C, int n) {
if (n == 1) {
// 基础情况:只有一个盘子,直接移动
C.push_back(A.back());
A.pop_back();
return;
}
// 1. 将 A 上方的 n-1 个盘子移到辅助柱 B
dfs(A, C, B, n - 1);
C.(A.());
A.();
(B, A, C, n - );
}
{
n = A.();
(A, B, C, n);
}
};


