对汉诺塔递归算法的理解(图解,附完整代码实现)
前情提要:
首先说一下汉诺塔游戏的规则:如下图所示,有三个柱子A,B,C,我们要做的是把A柱的所有圆盘,全部转移到C柱上,转移时遵循的规则如下:
1、每次只能移动一个圆盘
2、所有的大圆盘必须在小圆盘的下面
过程分析
首先假设只有一个圆盘,我们将其编号为1,如下图所示,那么这时候只需要将A直接移到C即可:
再假设有两个圆盘,我们看到移动过程如下:
步骤1:先将1号盘从A移动到B;
步骤2:再将2号盘从A移动到C;
步骤3:最后将1号盘从B移动到C,完成转移。
好了,请读者有点耐心,我们再看看三个圆盘的转移过程是怎样进行的:(此处用文字进行描述,请读者发挥想象)
首先三个圆盘放在A柱上,按从上到下的顺序依次编号为1,2,3(最小的为1,最大的为3),我们先不考虑3号盘,而只考虑上面两个小一点的圆盘(编号1,2),而此前我们已经分析了两个圆盘的移动过程,那么这两个圆盘该移动到哪根柱子呢?目前只有B柱,C柱可选,而C柱肯定不行,因为C柱是目标柱,那么我们只能把1,2号盘从A柱移动到B柱,借助C柱,则移动过程为:A->C, A->B,C->B。此时,1,2号盘已经到达B柱,再把最大的三号盘,直接移到C柱。此时工作快要完成了,目前的状态为:1,2号盘在B柱,3号盘已到达目的柱C柱,再接下来,把1,2号盘将B柱移动到C柱,转移工作就彻底结束,借助A柱,转移过程为:B->A,B->C,A->C。
通过上面第一段加红的文字,我们可以知道,A是作为起始柱,B作为目标柱,C作为辅助柱,通过第二段加红文字,我们可以知道,B是作为起始柱,A作为辅助柱,C作为目标柱。
那么此时,函数的写法,在脑海里大概就有了形状
函数定义
根据上面的分析,我们知道,函数的参数,有盘子,A,B,C三个柱子,所以,函数的签名为:move(n, a, b, c)。其中n表示圆盘的个数,a表示起始柱,b表示辅助柱,c表示目标柱。
根据上面对三个圆盘的分析,可得函数定义如下(Python代码):
1 def move(n, a, b, c): 2 if n == 1: 3 print a + \'-->\' + c 4 return 5 move(n - 1, a, c, b) 6 print a + \'-->\' + c 7 move(n - 1, b, a, c)
代码解释:
当n=1时,即当只有一个圆盘时,直接输出a -> c,即将圆盘从A移动到C(对应第2,3行代码)
当n>1时,就先处理前n-1个圆盘,将前n-1个圆盘从a移动到b柱,借助c柱(对应第5行代码),然后将第n个圆盘从a柱移动到c柱(对应代码第6行),最后将剩下的n-1个圆盘,将b柱移动到c柱,借助a柱(递归思想,请读者联合上面对三个圆盘的分析仔细斟酌)
调用代码如下:(4个圆盘)
1 move(4, \'A\', \'B\', \'C\')
结果如下:
A-->B A-->C B-->C A-->B C-->A C-->B A-->B A-->C B-->C B-->A C-->A B-->C A-->B A-->C B-->C