鱼C论坛

 找回密码
 立即注册
查看: 96|回复: 2

[技术交流] 关于汉诺塔视频的一些疑问。

[复制链接]
发表于 2025-3-10 08:23:55 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
关于《0基础入门学习Python》中视频和书里讲的汉诺塔递归,到底是递归时是遇到是先执行else里的第一个递归?还是一起执行else里的三条语句?我问AI,说先执行递归时,不会一次性执行 hanoi(n-1, x, z, y) + print() + hanoi(n-1, y, x, z) 三条语句,而是先执行第一个递归调用 hanoi(n-1, x, z, y),直到递归到底(n==1),从我的角度,按照AI的思路,有点明白了,小甲鱼那个思路我研究了好几天,还是没明白实参和形参到底是怎么变的?也不知道小甲鱼和AI那个正确?还是说小甲鱼那个视频我没有看懂?
微信图片_20250310082058.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2025-3-10 08:24:09 | 显示全部楼层
关于汉诺塔递归的详细解析

在汉诺塔问题中,递归调用的执行顺序如下:

  • 单个递归调用逐步展开: 当递归函数 `hanoi(n, x, y, z)` 被调用时,若 n > 1,它会先执行 `hanoi(n-1, x, z, y)`,即把 n-1 个盘子从起始柱移到辅助柱。
  • 执行打印语句: 待上一步的递归操作完成,会执行 `print()`,显示移动最大盘子的步骤。
  • 最后的递归调用: 接下来执行 `hanoi(n-1, y, x, z)`,将剩下的 n-1 个盘子从辅助柱移到目标柱。


递归调用的实参和形参变换具体如下:

-
hanoi(n-1, x, z, y)
:此调用体现将 n-1 个盘子从起始柱(x)移到辅助柱(y),通过目标柱(z)作为辅助。
-
hanoi(n-1, y, x, z)
:此调用体现将 n-1 个盘子从辅助柱(y)移到目标柱(z),通过起始柱(x)作为辅助。

总结:在递归中,函数不会一次性执行`else`中的所有语句,而是按顺序进行,每个递归调用都在解决一个更基础的问题,直至最简单的情况。继续按照视频的方法理解,应该更关注递归的逐步分解过程。

如果有相关代码,不妨参考一下:
def hanoi(n, x, y, z):
    if n == 1:
        print(x, "–>", z)
    else:
        hanoi(n-1, x, z, y)  # Step 1
        print(x, "–>", z)    # Step 2
        hanoi(n-1, y, x, z)  # Step 3

希望这些解释能帮助你更好地理解递归的执行过程!如果还有疑问,可以继续提问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-3-10 10:18:29 | 显示全部楼层
小甲鱼讲的和AI讲的并不冲突,只是侧重点不同:

  • 小甲鱼更偏向把汉诺塔的移动策略说得通俗易懂。
  • AI(或者说任何更“底层”一点的解释)则是告诉你,Python 在执行时的“顺序”和“栈式调用”机制。
  • 如果你感觉小甲鱼的“思路”还没消化透,可以多结合上面这个函数调用顺序的过程去理解。他们讲的并没有冲突,只是表达方式不同。

在 Python(以及绝大多数编程语言)里,函数调用是顺序执行的,并不会“同时”执行 else 里的三条语句。

也就是说:

  • 先执行 hanoi(n-1, x, z, y)
  • 等第一个递归全部执行完毕后,才会执行 print(x, '-->', z)
  • 然后再执行 hanoi(n-1, y, x, z)
  • 所以 AI 的说法——“先执行第一个递归调用,一直到递归结束后,再往下执行 print,然后再执行第二个递归”——是正确的。

为什么不会“同时”执行?

在 Python 中,当你调用一个函数时(比如 hanoi(n-1, x, z, y)),Python 会先进入这个函数,执行完它所有的代码(包括内部可能还有多层递归调用)之后,才会“返回”到调用它的地方,继续往下执行下一条语句。

这个过程是栈式调用,也就是常说的“后进先出”机制。

所以在 else 里:
else:
    hanoi(n-1, x, z, y)
    print(x, '-->', z)
    hanoi(n-1, y, x, z)
第一行 hanoi(n-1, x, z, y) 里包含了若干次递归,必须全部完成,才会回到 else 中,执行第二行 print(x, '-->', z)。

然后再调用第三行 hanoi(n-1, y, x, z) 并且要等这第三行的递归也全部执行完,这个 else 块才算彻底结束。


实参和形参是怎么变的?

很多同学纠结的一个问题是:为什么 hanoi(n-1, x, z, y) 里参数的位置会调换?

这里就涉及到“形参”和“实参”的区别。

在函数定义处,比如:
def hanoi(n, x, y, z):
    ...
n, x, y, z 是形参(形式参数)。
当你调用 hanoi(3, 'A', 'B', 'C') 时,3, 'A', 'B', 'C' 就是实参(实际参数)。

它们将按顺序分别传给 n, x, y, z。

所以当你在 else 里写:
hanoi(n-1, x, z, y)
n-1 传给 n(形参)
x 传给 x(形参)
z 传给 y(形参)
y 传给 z(形参)
这样就形成了“搬家”式的参数重新排列。

递归调用时,形参与实参之间不断进行“对应赋值”,从而把原来函数里 x, y, z 的含义换了位置。

用一个小例子走一遍(以 n=3 为例)

假设最开始调用:
hanoi(3, 'A', 'B', 'C')
此时 n=3, x='A', y='B', z='C'。

因为 n != 1,走到 else:
调用 hanoi(2, 'A', 'C', 'B')
这里 n-1=2, x='A', z='C' 传给第二个参数,y='B' 传给第四个参数。

进入 hanoi(2, 'A', 'C', 'B') 后,它本身又是 n=2 != 1,所以再次走 else:调用 hanoi(1, 'A', 'B', 'C')

这里 n=1,满足 if n == 1,直接 print("A --> C"),然后返回。

执行 print("A --> B")

调用 hanoi(1, 'C', 'A', 'B')

这里又是 n=1,打印 "C --> B",然后返回。

至此,hanoi(2, 'A', 'C', 'B') 整个执行完毕,才返回到 hanoi(3, 'A', 'B', 'C')。

执行 print("A --> C")。

调用 hanoi(2, 'B', 'A', 'C')

同理,会依次打印 "B --> A"、"B --> C"、"A --> C"。

这样所有的步骤都完成后,hanoi(3, 'A', 'B', 'C') 才算执行完毕。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-3 04:30

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表