davidmou 发表于 2023-10-7 13:06:17

递归问题

def moveDisk(fp, tp):
    print("moving disk from %d to %d\n" % (fp, tp))
def moveTower(height, fromPole, toPole, withPole):
    if height >= 1:
      moveTower(height-1, fromPole, withPole, toPole)
      moveDisk(fromPole, toPole)
      moveTower(height-1, withPole, toPole, fromPole)
moveTower(3,1,3,2)

在执行完moveTower(3,1,3,2)后,会执行moveTower(2,1,3,2),然后再执行moveTower(1,2,3,2),不是会无限循环吗,moveDisk(fromPole, toPole)
       moveTower(height-1, withPole, toPole, fromPole)代码就执行不了,但事实上时可以执行的,这是为什么

isdkz 发表于 2023-10-7 13:07:23

在递归函数中,当height>=1时,会不断地执行moveTower函数,直到height=1时,执行moveDisk函数,然后再继续执行moveTower函数。在执行moveTower(1, 2, 3, 2)时,由于height=1,所以会直接执行moveDisk(2, 3)函数,然后再返回到上一层递归函数moveTower(2, 1, 3, 2)中,执行moveTower(2, 1, 3, 2)中的moveTower(1, 1, 2, 3)函数,由于height=1,所以会直接执行moveDisk(1, 2)函数,然后再返回到上一层递归函数moveTower(3, 1, 3, 2)中,执行moveTower(3, 1, 3, 2)中的moveTower(2, 2, 3, 1)函数,由于height=2,所以会执行moveTower(2, 2, 3, 1)中的moveTower(1, 2, 3, 1)函数,由于height=1,所以会直接执行moveDisk(2, 3)函数,然后再返回到上一层递归函数moveTower(2, 2, 3, 1)中,执行moveDisk(1, 2)函数,最后再返回到moveTower(3, 1, 3, 2)函数中,执行moveTower(3, 1, 3, 2)中的moveTower(2, 1, 3, 2)函数,由于height=1,所以会直接执行moveDisk(2, 3)函数,然后再返回到上一层递归函数moveTower(3, 1, 3, 2)中,执行moveTower(3, 1, 3, 2)中的moveTower(1, 2, 3, 2)函数,由于height=1,所以会直接执行moveDisk(1, 2)函数,最终完成整个递归过程。因此,不会出现无限循环的情况。

Mike_python小 发表于 2023-10-7 13:08:04

您的理解有一点混淆。在递归调用时,每次递归都会传入新的参数值,并且在特定条件下停止递归,因此不存在无限循环的情况。

让我们来详细解释一下递归的执行过程:

1. 首先,调用 moveTower(3, 1, 3, 2)。
2. 进入 moveTower 函数,传入参数 (3, 1, 3, 2)。
3. 因为 height >= 1,所以进入递归。
4. 首先调用 moveTower(2, 1, 2, 3)。注意:此处辅助柱和目标柱交换了位置,是因为在本次递归中,辅助柱变成了目标柱,目标柱变成了辅助柱。
5. 进入 moveTower 函数,传入参数 (2, 1, 2, 3)。
6. 再次进行递归调用,调用 moveTower(1, 1, 3, 2)。
7. 进入 moveTower 函数,传入参数 (1, 1, 3, 2)。
8. 因为 height >= 1,所以进行递归调用。
9. 调用 moveTower(0, 1, 2, 3)。注意:在这里,height-1 的值为 0,所以不会继续递归调用。
10. 返回到上一层递归调用 moveTower(1, 1, 3, 2)。
11. 调用 moveDisk(1, 3),输出移动盘子的操作。
12. 再次进行递归调用 moveTower(0, 2, 3, 1)。同样,height-1 的值为 0,不会递归调用。
13. 返回到上一层递归调用 moveTower(2, 1, 2, 3)。
14. 调用 moveDisk(1, 2),输出移动盘子的操作。
15. 再次进行递归调用 moveTower(1, 3, 2, 1)。
16. 进入 moveTower 函数,传入参数 (1, 3, 2, 1)。
17. 同样进行递归调用 moveTower(0, 3, 1, 2),并返回。
18. 调用 moveDisk(3, 2),输出移动盘子的操作。
19. 再次进行递归调用 moveTower(0, 1, 2, 3),并返回。
20. 返回到上一层递归调用 moveTower(3, 1, 3, 2)。
21. 调用 moveDisk(1, 3),输出移动盘子的操作。
22. 再次进行递归调用 moveTower(2, 2, 3, 1)。
23. 进入 moveTower 函数,传入参数 (2, 2, 3, 1)。
24. 同样进行递归调用 moveTower(1, 2, 1, 3),并返回。
25. 调用 moveDisk(2, 3),输出移动盘子的操作。
26. 再次进行递归调用 moveTower(1, 1, 3, 2)。
27. 进入 moveTower 函数,传入参数 (1, 1, 3, 2)。
28. 同样进行递归调用 moveTower(0, 1, 2, 3),并返回。
29. 调用 moveDisk(1, 2),输出移动盘子的操作。
30. 返回到上一层递归调用 moveTower(2, 2, 3, 1)。
31. 调用 moveDisk(3, 1),输出移动盘子的操作。
32. 再次进行递归调用 moveTower(1, 3, 2, 1)。
33. 进入 moveTower 函数,传入参数 (1, 3, 2, 1)。
34. 同样进行递归调用 moveTower(0, 3, 1, 2),并返回。
35. 调用 moveDisk(3, 2),输出移动盘子的操作。
36. 返回到上一层递归调用 moveTower(2, 2, 3, 1)。
37. 再次进行递归调用 moveTower(1, 2, 1, 3),并返回。
38. 调用 moveDisk(2, 3),输出移动盘子的操作。
39. 返回到上一层递归调用 moveTower(3, 1, 3, 2)。
40. 返回到主程序。

所以,通过以上的递归过程,每个递归调用都会返回到上一层,并依次执行后续的代码。不存在无限循环的问题。

希望这样的解释能够清楚地回答您的疑问。如果还有其他问题,请随时提出。

球一个最佳答案谢谢啦!这对我非常重要!{:10_254:}{:10_254:}{:10_254:}
页: [1]
查看完整版本: 递归问题