在刚学廖雪峰廖大佬的python3教程中的递归时,前面的内容理解都觉得还行,到了做汉诺塔的练习时会觉得有些发懵,后面多看几遍和练习后也就理解了。
因为遇到有人在问这个问题咋理解,因此写下我的想法,希望能帮助到更多人来理解这个问题
题目:
汉诺塔的移动可以用递归函数非常简单地实现。
请编写move(n, a, b, c)
函数,它接收参数n
,表示3个柱子A、B、C中第1个柱子A的盘子数量,然后打印出把所有盘子从A借助B移动到C的方法,例如:
def move(n, a, b, c):
if n == 1:
print(a, '-->', c)
...代码串...
# 期待输出:
# A --> C
# A --> B
# C --> B
# A --> C
# B --> A
# B --> C
# A --> C
move(3, 'A', 'B', 'C')
讲答案之前,容我举一个递归的例子:
def fact(n):
if n==1:
return 1
return n * fact(n - 1)
这是一个求阶乘 y = n! 的函数,如果你看懂了,继续往下看,没看懂,请先点击廖雪峰大佬的教程看看
廖雪峰教程递归链接
其实刚开始我也不会做这道题,一个是对递归的理解不够深刻,另一个是对汉诺塔的解法不是很了解,后面还百度看了下汉诺塔别人是怎么玩的
在分析之前,我解释下汉诺塔的解法是怎么运行的,它到底跟递归又有什么关系
举个最简单的例子,就是题目这样的,有A、B、C 三个柱子,A中有三个盘子
我得把A中绿、黄、红三个圆盘转移到C中,一次只能移动一个,并且也是从上往下按绿、黄、红的顺序摆放
逻辑思路:
1、绿、黄按顺序放在B
2、红从A去C
3、绿在从B去A
4、黄从B到C
5、绿从A到C
一句话解释:
n个盘子,把【1~(n-1)】个盘子看成一个整体,实际就2个盘子,上面的盘子放中转柱,下面的放目标柱。
当每次取完最下面的盘子放到 C 时,再按照这思路把剩余的盘子最下面的盘子空出来,这样看,是不是像递归呢?
(即循环两个步骤:1、放在第n盘上面的所有盘子从 转移柱—>中转柱 2、第n盘 从 转移柱—>目标柱 )
(PS:转移柱和中转柱不是固定的,两者相互转换)
代码分析:
def move(n, a, b, c):
if n == 1:
print(a,'-->', c)
else:
move(n-1, a, c, b) #1
move(1, a, b, c) #2
move(n-1, b, a, c) #3
move(3, 'A', 'B', 'C')
!!!一定要注意 move()中的 n 是指放在a柱(转移柱)上的盘子个数, a、b、c,分别代表(转移柱、中转柱、目标柱),跟 上图的 A、B、C是有不同意义的
-
if
先讲下if,意思很明显,当a柱(转移柱)上的盘子为1时,把它从 a—>c
-
else
1. #1
move(n-1, a, c, b)
这里的 n-1 很好理解,就是上面说的把【1~(n-1)】个盘子看成一个整体,看成一个新的递归,为什么是 a, c, b ,而不是 a、b、c呢?
这里一定要理解为何是 a, c, b。
因为a、c、b 这样的顺序,就是先把 B 当成了目标柱,C 当成了中转柱,把 【1~(n-1)】转移到 B ,才能把 A 中最底层的盘子空出来
2. #2
move(1, a, b, c)
这个就不用讲了, A 中最底层的盘子空出来了,自然是把它从 A 放到 C
3. #3
move(n-1, b, a, c)
这时,开启一个新的轮回了,第 n 个盘子在 C 中,【1~(n-1)】个盘子在 B(新的转移柱) ,所以你还不懂什么意思吗?