Python:用最简单的方式弄懂汉诺塔问题 还有递归

学习Python到现阶段,所接触到的知识,让我认为编程,其实就是我定义好程序,系统再将结果计算出来。
从之前的裴波那契数列到这个汉诺塔,似乎都是按照数学函数来编程序,展现出的只是函数结果,这和我想的不一样,并没有更多的智能,跟计算器本质上没区别。

言归正传,在汉诺塔中,按逻辑来说,只要明白了圆盘是按什么特定顺序移动的,就能非常简单的编出一个让系统演示圆盘如何移动的程序。

汉诺塔的规则

有A、B、C三根石柱子,在一根石柱子上,从大到小摞着N个圆盘。现在需将圆盘从这根柱子按从大到小的顺序重新摆放到另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。

开始游戏

题目的意思很简单,可以简单的理解为就是把A柱上的n个盘子,一步一步的移动到C柱上。
那么如何进行这个过程呢?
1.首先,在A柱上有n个盘子,我们需要把这n个盘子移动到目标柱C柱上。
汉诺塔示意

2.根据规则,我们先将A柱上的n-1个盘子,通过不停的摆放移动,一步一步的全部移动到了B柱上。这时候A柱上只剩下了一个盘子,可以直接移动到目标柱C柱上。
这里写图片描述

3.最后通过同样的操作,将B柱上的n-1个盘子给移动到C柱上。
这里写图片描述

编程方式

上面的图解是为了形象的说明,汉诺塔游戏可以剖析成三个部分,而这三个部分就可以浓缩为三行程序,

hanoi(n-1,a,c,b)#将n-1个盘子从a柱借助c柱移动到b柱
hanoi(1,a,b,c)#将A柱上最后一个盘子直接移动到c柱
hanoi(n-1,b,a,c)#将b柱上n-1个盘子借助a柱移动到c柱

这就是这个程序的编程思想,用大白话给解释了一遍。

下面是完整的程序

def hanoi(n,a,b,c):
    if n==1:#当盘子为一个时,直接从a柱移动到c柱
        print(a,'-->',c)
    else:
        hanoi(n-1,a,c,b)
        hanoi(1,a,b,c)
        hanoi(n-1,b,a,c)
        
hanoi(3,'A','B','C')#假设盘子为3个,输出盘子移动的结果

A --> C
A --> B
C --> B
A --> C
B --> A
B --> C
A --> C

这里边运用了递归,函数重复的调用自己,程序按照我们编写的代码不停的运行着,先将n-1个盘子移动到b柱,再从b柱移动到c柱,这是一个很神奇的过程,现在我也只能知其然不知其所以然。希望随着日后的不断学习,能爆发出一丝灵感,顿悟。

看到这里,可能大家还是有很多疑问,比如:函数定义的a,b,c三个变量的赋值在系统内部是如何变化的,这个程序递归的流程顺序是什么样的。可以参考以下的程序和图片,非常nice!

利用locals()方法寻值

locals()方法的功能为返回当前作用域内的局部变量和其值组成的字典,用在这里再合适不过了。

def hanoi(n,a,b,c):
    if n==1:
        print(a,'-->',c)
    else:
        print(locals()) 
        hanoi(n-1,a,c,b)
        print(locals()) 
        hanoi(1,a,b,c)
        print(locals()) 
        hanoi(n-1,b,a,c)
        print(locals()) 
hanoi(3,'A','B','C')
#a,b,c变量赋值的变化,从n=3开始
{'c': 'C', 'b': 'B', 'a': 'A', 'n': 3}
{'c': 'B', 'b': 'C', 'a': 'A', 'n': 2}
A --> C  #每当运行到n=1时,输出内容
{'c': 'B', 'b': 'C', 'a': 'A', 'n': 2}
A --> B
{'c': 'B', 'b': 'C', 'a': 'A', 'n': 2}
C --> B
{'c': 'B', 'b': 'C', 'a': 'A', 'n': 2}
{'c': 'C', 'b': 'B', 'a': 'A', 'n': 3}
A --> C
{'c': 'C', 'b': 'B', 'a': 'A', 'n': 3}
{'c': 'C', 'b': 'A', 'a': 'B', 'n': 2}
B --> A
{'c': 'C', 'b': 'A', 'a': 'B', 'n': 2}
B --> C
{'c': 'C', 'b': 'A', 'a': 'B', 'n': 2}
A --> C
{'c': 'C', 'b': 'A', 'a': 'B', 'n': 2}
{'c': 'C', 'b': 'B', 'a': 'A', 'n': 3}

将上面的赋值变化表结合下面的程序运行流程图,对初学者初步认识递归还是很有帮助的。
这里写图片描述

写这篇博客前,我觉得我已经懂递归了,结果写到一半,看着这流程图又发现了新的问题,一时半会儿还研究不出来,日后再说日后再说。

10月22日:
汉诺塔函数延伸。

def move(n,a,b,c):
    if n == 1:
        print(a,b,c)
    else:
        move(n-1,c,b,a)
move(2,1,2,3)
------------------------------
3 2 1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值