【数据结构|汉诺塔问题】汉诺塔问题以及递归思想实现


文章部分图片来源: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.汉诺塔问题思考和分析

    我们会发现无论我们怎么移动都离不开以下思路:

  1. 先把上面的全部移走
  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也结束全部执行完毕。栈过程其实有问题最后一页补全。
在这里插入图片描述
在这里插入图片描述

Step6 :总结

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱喝冰红茶的方舟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值