(小白也能看懂)汉诺塔代码实现

廖雪峰递归函数作业看到我一脸懵,多方查证资料没找到很好的解释。网上关于汉诺塔的原理有很多文章,但是都没能很好的解释为什么要这样编写代码,这里我以python为例,解释如何从基本原理抽象到数学模型,再用代码实现。

大家都很清楚这个代码可以利用递归轻松实现,这里我将四个圆盘的搬运过程用表格的形式呈现,方便大家看清规律。

最底层的圆盘永远只需要移动一步A-C,每层圆盘的移动次数均为2的n-1次方。

那么首先我们先写第一段代码,表示最底层圆盘的运动:

def move(n, a, b, c):
    if n==1:
        print('%s-->%s'%(a,c))

很好理解,我们完成了最底层圆盘的运动表达,现在看第二层圆盘的运动情况。

我们很容易发现运动过程,看上去就像一个树杈分成了两端,每次分叉都会1变2,2变4,因为最底层只需要移动一次,很容易得出总的运动次数为2^n-1。

那么编程逻辑也很清楚了,只需要在A-C,也就是最底层圆盘运动的左,右利用函数自动递归即可。

第一步的代码已经有了,下面先看左侧有什么规律。

很容易发现只要是分支向左的就必定是A-?,再看一眼其他的位置发现是C-?,或者B-?,由此我们得出一个规律,就是左侧的分支,与分支开始时的字母有关,左侧字母固定,右侧字母不断变换,那么我们试着写一下:

def move(n, a, b, c):
    if n==1:
        print('%s-->%s'%(a,c))
    else:
        n=n-1
        move(n,a,c,b)
        print('%s-->%s'%(a,c))
move(3,'A','B','C')

结果如图,我们发现只输出了左侧分支的内容,与图表中的内容一致。为了保持a不变,b,c不断调换,在move中,我调换了b,c的位置,move(n, a, b, c)-->move(n, a, c, b)。

由此我们可以推出右侧内容的代码,右侧字母固定,左侧字母轮换,那就保持c不变,a,b调换位置-->move(n, b, a, c),补全代码:

def move(n, a, b, c):
    if n==1:
        print('%s-->%s'%(a,c))
    else:
        n=n-1
        move(n,a,c,b)
        print('%s-->%s'%(a,c))
        move(n,b,a,c)
(move(3,'A','B','C'))

与预期结果一致,实际上代码可以不要上面的部分,直接代入递归。

def move(n, a, b, c):
    if n>0:
        n=n-1
        move(n,a,c,b)
        print('%s-->%s'%(a,c))
        move(n,b,a,c)

思考

还有没有别的方式实现汉诺塔的代码模型?

结合表格中的规律,我们横向来看,似乎所有的圆盘的运动规律都是一致的!

奇数圆盘起步是A-B,B-C,C-A,偶数圆盘起步是A-C,C-B,B-A

最顶上的圆盘起步是2^0,此后每2^1次方动一下

第n个圆盘就是2^(n-1)起步,此后每2^n次方动一下

不过这样写出来的代码含有诸多判断循环语句,复杂程度就大幅增加了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值