- 基准情形: 必须由某些基准情形,它无需递归就能解出
- 不断推进: 对于那些需要递归的情形,每一次递归调用都必须要使求解的状况朝接近基准情形的方向推进
- 设计法则: 假设所有的递归调用都能运行
- 合成效益法则: 在求解同一问题的同一实例时, 切勿在不同的递归调用中做重复的工作
_________________摘自《数据结构与算法分析(机械工业出版社Mark Allen Weiss著)》
汉诺塔是一个发源于印度的益智游戏,也叫河内塔。相传它源于印度神话中的大梵天创造的三个金刚柱,一根柱子上叠着上下从小到大64个黄金圆盘。大梵天命令婆罗门将这些圆盘按从小到大的顺序移动到另一根柱子上,其中大圆盘不能放在小圆盘上面。当这64个圆盘移动完的时候,世界就将毁灭。
汉诺塔问题源于印度神话
那么好多人会问64个圆盘移动到底会花多少时间?那么古代印度距离现在已经很远,这64个圆盘还没移动完么?我们来通过计算来看看要完成这个任务到底要多少时间?
我们首先利用数学上的数列知识来看看F(n=1)=1,F(n=2)=3,F(n=3)=7,F(n=4)=15……F(n)=2F(n-1)+1;
我们使用数学归纳法可以得出通项式:F(n)=2^n-1。当n为64时F(n=64)=18446744073709551615。
我们假设移动一次圆盘为一秒,那么一年为31536000秒。那么18446744073709551615/31536000约等于584942417355天,换算成年为5845.54亿年。
目前太阳寿命约为50亿年,太阳的完整寿命大约100亿年。所以我们整个人类文明都等不到移动完整圆盘的那一天。
使用递归的算法解决汉诺塔问题,是了解编程中递归算法思想的基础理念。
首先,我们需要了解一下汉诺塔游戏中一阶到N阶的解法是否有规律性???
现在我们来分析一下:
我们设定三个柱子A,B,C。 最终的结果是将环从 A 移动到 C。
假设N为汉诺塔的层数。
当 N = 1 时,很简单,只需要把圆环从 A 移动到 C 即可。
当 N = 2 时,需要操作三步:
上面这张动图演示了2阶汉诺塔移动的过程。
当 N = 3 时,共需要 7 步 ……
3 阶大家都可以比较轻松解开。
那么这里面有什么规律呢,是否可以用递归来解决呢?
请看图片
上面左面的图片为 2 阶汉诺塔移动步骤第一步,假设最大环不存在,只有一个环。如果我们再假设把 B 柱和 C 柱交换位置,那么是否就和 1 阶汉诺塔移动的步骤是一样呢?
这就是解决汉诺塔的规律!!!
就是: 每次都把 “A” 柱上的环移动到 “C” 柱,当然这里的 A、C柱不是固定的!也可以理解为始终操作 1 阶汉诺塔的解答步骤
我在学习的时候这里会比较混乱,需要一些理解能力
然后接下来继续
2 阶汉诺塔第二步: A 移动到 C, 这时已经将最大环移动到了 C 柱上
2 阶汉诺塔最后一步:
情况如上面左图所示, 假设 A 柱和 B 柱交换位置,再次操作一阶汉诺塔步骤.即 A 移动到 C
到此为止,2阶汉诺塔解决完毕.
我们总结出了2阶汉诺塔的操作步骤:
首先交换 B 柱和 C 柱的位置 ,然后执行 1 阶汉诺塔解答步骤 (*逻辑中每次操作后恢复柱子的真实摆放位置,即ABC)
执行 1 阶汉诺塔解答步骤
交换 A 柱和 B 柱的位置,然后执行 1 阶汉诺塔解答步骤 (*逻辑中每次操作后恢复柱子的真实摆放位置,即ABC)
PS:这里困扰我的是,逻辑中移动柱子位置后,并不是真的移动,每一步操作后他们的位置还是 A柱 B柱 C柱,可能只是我自己的理解能力问题,这里标记出来,希望有和我一样问题的朋友可以从这里得到感悟
这里只解决了 2 阶,那么 N 阶的汉诺塔怎么解决呢?
三阶的时候,我们可以把最大环除外的环视为一个环,然后执行上面 2 阶的方法
四阶的时候,我们可以把最大环除外的环视为一个环,然后执行上面 2 阶的方法
五阶的时候……
.
..
...
那么,我们已经找到了解决汉诺塔的递归算法
下面我们用python来实现.
这里的关键在于对三个步骤的代码实现.
def hanoi(n, a, b, c):
if(n == 1):
print(a, '-->', c)
else:
#n-1视为一个整体,然后调整柱子的位置,最终n=1时,执行1阶汉诺塔解决步骤
hanoi(n-1, a, c, b)
#此行为最大环移动,执行1阶汉诺塔解决步骤
print(a, '-->', c)
#n-1视为一个整体,然后调整柱子的位置,最终n=1时,执行1阶汉诺塔解决步骤
hanoi(n-1, b, a, c)
num = int(input('请输入汉诺塔的层数:'))
hanoi(num, 'a柱', 'b柱', 'c柱')
执行结果为:
此文为鄙人第一次写博客分享,实属因为自己悟性比较差,理解了一天算法都没有领悟到其中真意,参考了 PharahBai 的文章后,决定按照自己遇到的问题,理解上的误区,记录并分享出来,希望能够帮助到他人
参考文章网址 https://blog.csdn.net/xb2355404/article/details/79144451