文章目录
文章部分图片来源:https://blog.csdn.net/m0_68989458/article/details/124087487?ops_request_misc=&request_id=&biz_id=102&utm_term=%E6%B1%89%E8%AF%BA%E5%A1%94&utm_medium=distribute.pc_search_result.none-task-blog-2 allsobaiduweb~default-1-124087487.nonecase&spm=1018.2226.3001.4187
学习思路来源:B站懒猫老师视频
0.汉诺塔问题引入
很多人其实都玩过这类游戏,通过下面图片进行深入了解
图片原文链接:关于汉诺塔问题
1.汉诺塔问题分析
1.1 一阶汉诺塔
A -> C即可
1.2 二阶汉诺塔
A -> B
A -> C
B -> C
2.汉诺塔问题思考和分析
我们会发现无论我们怎么移动都离不开以下思路:
- 先把上面的全部移走
- 最大的移动到C
于是:
(1)当 n == 1时,直接将盘子从 A 移动到C
(2)当 n > 1时,可以拆分成3大步骤
①将 n– 1 个盘子从 A 移动到B
②将编号为 n 的盘子从 A 移动到C
③将 n– 1 个盘子从 B 移动到C
# Python完整代码:
def move(pfrom, pto):
global i
print("第%d步:%s ---> %s" % (i, pfrom, pto))
i += 1
# hanoi函数表示把n个盘子从起点a经过b到达c
def hanoi(n, a, b, c):
if n == 1:
move(a, c)
else:
hanoi(n - 1, a, c, b) # 句1
move(a, c)
hanoi(n - 1, b, a, c) # 句2
n = int(input("请输入盘数:"))
print("具体走法步骤如下:")
hanoi(n, "A", "B", "C")
print("一共需走%d步" % (i - 1))
3.三阶汉诺塔为例递归过程分析
但是实际上我对递归流程并不是很理解,然后结合课程对三阶汉诺塔进行分析:
Step 1 : 3个从A移动到C转为先将2个从A借助C移动到B
hanoi(3, "A", "B", "C")调用函数
n != 1 执行else
hanoi(2, "A", "C" ,"B")//按照调用参数顺序
但是:hanoi(3, “A”, “B”, “C”)还没有执行完在递归的时候进入了一个新的状态hanoi(2, “A”, “C” ,“B”),由于 n-1 所以新状态最后肯定会执行完(可能会新状态中进入新状态暂时不考虑),执行完会继续执行hanoi(3, “A”, “B”, “C”)后面内容,所以需要保存当前状态(那一句、参数列表),需要引用栈来实现
Step2 : 2个从A借助C移动到B转为先将1个从A借助B移动到C
# Step2:状态1入栈后执行hanoi(2, "A", "C" ,"B")
# hanoi函数表示把n个盘子从起点a经过b到达c
def hanoi(n, a, b, c):
if n == 1:
move(a, c)
else:
hanoi(n - 1, a, c, b) # 句1
move(a, c)
hanoi(n - 1, b, a, c) # 句2
n = int(input("请输入盘数:"))
print("具体走法步骤如下:")
hanoi(n, "A", "B", "C")
print("一共需走%d步" % (i - 1))
hanoi(2, "A", "C" ,"B")// 注意参数顺序
n != 1 执行else
hanoi(1, "A", “B" ,“C")//按照调用参数顺序
但是:hanoi(2, “A”, “C” ,“B”)还没有执行完在递归的时候进入了一个新的状态hanoi(1, “A”, “B" ,“C"),由于 n-1 所以新状态最后肯定会执行完(可能会新状态中进入新状态暂时忽略),执行完会继续执行hanoi(2, “A”, “C” ,“B”)后面内容,所以需要保存当前状态(那一句、参数列表),需要引用栈来实现
于是会继续压进栈
Step3 : 先将1个从A借助B移动到C
# Step3:执行hanoi(1, "A", “B" ,“C")
# hanoi函数表示把n个盘子从起点a经过b到达c
def hanoi(n, a, b, c):
if n == 1:
move(a, c)
else:
hanoi(n - 1, a, c, b) # 句1
move(a, c)
hanoi(n - 1, b, a, c) # 句2
n = int(input("请输入盘数:"))
print("具体走法步骤如下:")
hanoi(n, "A", "B", "C")
print("一共需走%d步" % (i - 1))
hanoi(1, “A”, “B" ,“C")// 注意参数顺序
n == 1 执行else
move(a, c)//按照调用参数顺序
输出:第1步:A —> C
此状态结束
Step4 : 递归结束后返回到栈顶的状态—语句和参数列表继续执行
# Step4:状态2入栈后执行hanoi(1, "A", “B" ,“C")
# hanoi函数表示把n个盘子从起点a经过b到达c
def hanoi(n, a, b, c):
if n == 1:
move(a, c)
else:
hanoi(n - 1, a, c, b) # 句1
move(a, c)
hanoi(n - 1, b, a, c) # 句2
n = int(input("请输入盘数:"))
print("具体走法步骤如下:")
hanoi(n, "A", "B", "C")
print("一共需走%d步" % (i - 1))
即hanoi(2, “A”, “C” ,“B”)// 注意参数顺序
语句运行结束向下继续执行move(a, c)
输出:第2步:A —> B
向下继续执行hanoi(1, “C", “A" ,“B”)//
即输出:第3步:C —> B,直接输出了简化
状态2全部执行结束,出栈
Step5 : 状态2全部执行完执行状态1
# Step5:状态2全部执行完执行状态1
# hanoi函数表示把n个盘子从起点a经过b到达c
def hanoi(n, a, b, c):
if n == 1:
move(a, c)
else:
hanoi(n - 1, a, c, b) # 句1
move(a, c)
hanoi(n - 1, b, a, c) # 句2
n = int(input("请输入盘数:"))
print("具体走法步骤如下:")
hanoi(n, "A", "B", "C")
print("一共需走%d步" % (i - 1))
向下继续执行move(a, c)
输出:第4步:A —> C
向下继续执行hanoi(2, “B", “A" ,“C")
又进入一个新状态、记录为状态3,入栈
2 != 1,执行else语句
hanoi(1, “B", “C" ,“A")
输出:第5步:B —> A
然后继续执行move(a, c)
输出:第6步:B —> C
继续执行hanoi(1, “A", “B" ,“C")
输出:第7步:A —> C
状态3也结束,返回状态1,刚好也是最后一个语句,状态1也结束全部执行完毕。栈过程其实有问题最后一页补全。