印度有个古老传说:在世界的中心贝拿勒斯的神庙里,一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候,在其中一根针上穿好了由大到小的64片金片,这就是汉诺塔。不论白天黑夜,一群沉默的僧侣在移动这些金片:一次只移动一片,不管在哪根针上,小片必须在大片上面。僧侣们预言,当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消失。
汉诺塔模型如上图,问题化成将A中的盘片最后转移到B中,可以借助中间一根柱子。
你上来就直接移动几个盘片,摆弄了几次,你放弃了,因为太繁琐了。碰到这种问题,我们一般是简化。
最简化的,是假设只有一个盘片,那太容易了,直接移到B;
次简化的,假设有两个盘片,那就把第一个小盘片移到中间的柱子,然后把底下的大盘片移到B,再之后把小盘片从中间移到B。
进一步,假设有三个盘片,步骤一是把第一个小盘片移到B,然后步骤二把第二个盘片移到中间,再之后步骤三把B上的小盘片移到中间,这样上面的两个盘片整体移到中间柱子了,所以步骤四就是把A剩下的底下那个大盘片移动到B,步骤五就是把中间柱子最上面的小盘片移动到A,步骤六把中间柱子下面的盘片移动到B,最后步骤七把A的小盘片移动到B。完毕。如下图所示:
我们仔细看上面的步骤,会发现一个关键点,就是对三个盘片来讲,就是要先想方设法让上面的两个整体移动到中间柱子,剩下的大盘片就直接移动到最后的目标了。
推广这个结论,对N个盘片,我们的任务就变成了先将N-1个盘片整体移动到中间柱子,然后就好办了,直接移动底下最大的那个。接下来的任务就是同样的了,不同之处在于少了一个盘片。这样一步步剩下N-1,然后N-2,...
所以,这个思路,就是递归的思路。n个盘片,123三根柱子,我们先把n-1个盘片整体从柱子1移动到柱子2,再把底下的第n个盘片从柱子1移动到柱子3,最后再把n-1个盘片整体从柱子2移到柱子3。程序实现:
def hanoi(n,a,b,c):
if n == 1:
print(n,a,c)
return
hanoi(n-1,a,c,b)
print(n,a,c)
hanoi(n-1,b,a,c)
print(hanoi(3,1,2,3))
解读一下。一步步跟踪。
第一层,hanoi(3,1,2,3),执行 hanoi(n-1,a,c,b)语句即 hanoi(2,1,3,2),递归进去,进入第二层;
第二层,hanoi(2,1,3,2),执行hanoi(n-1,a,c,b)语句即hanoi(1,1,2,3),递归进去,进入第三层;
第三层,hanoi(1,1,2,3),执行print(n,a,c)语句即print(1,1,3),返回到第二层;
继续第二层,执行print(n,a,c)语句即print(2,1,2),再执行hanoi(n-1,b,a,c)语句即hanoi(1,3,1,2),递归进去,再次进入第三层;
第三层,hanoi(1,3,1,2),执行print(n,a,c)语句即print(1,3,2),返回到第二层;
第二层语句都执行完了,返回第一层;
继续第一层,执行print(n,a,c)语句即print(3,1,3),再执行hanoi(n-1,b,a,c)语句即hanoi(2,2,1,3),递归进去,再次进入第二层;
第二层,hanoi(2,2,1,3),执行hanoi(n-1,a,c,b)语句即hanoi(1,2,3,1),递归进去,进入第三层;
第三层,hanoi(1,2,3,1),执行print(n,a,c)语句即print(1,2,1),返回到第二层;
继续第二层,hanoi(2,2,1,3),执行print(n,a,c)语句即执行print(2,2,3),再执行hanoi(n-1,b,a,c)即hanoi(1,1,2,3),递归进去,进入第三层;
第三层,hanoi(1,1,2,3),执行print(n,a,c)语句即print(1,1,3),返回到第二层;
第二层语句执行完了,返回第一层;
第一层语句也执行完了,完毕。
最后输出结果:
1 1 3
2 1 2
1 3 2
3 1 3
1 2 1
2 2 3
1 1 3
上面的调用过程可以用一个图直观展示:
从这个图我们可以看到,递归的调用过程是一棵树,逐层展开的逐层返回。我们对递归的详细介绍也到此为止,后面不这么一步步跟踪了。你要熟悉这个过程。
我们计算一下,N片要移动多少次?我们从上面代码看到了,f(k+1)=2*f(k)+1,不难证明f(n)=2n-1。从调用图示也可以看出来,第一层有一次,第二层有两次,第三层有四次。
按照传说,Hanoi塔上有64个盘片,所以一共要移动的次数为f(64)= 264-1=18446744073709551615。这是一个难以想象的大数。
如果这些僧侣一秒钟移动一次,大约要花584554049253.855年,也就是说需要5845亿年以上,而地球存在不过45亿年,太阳系的预期寿命据说也就是数百亿年。Hanoi塔搬完的那个时候,我们熟悉的一切,地球,太阳,星空,文明,估计都已经不存在了。
所以传说当僧侣们搬完这些金片的时候这世界就会消失,或许没有错啊。