今天突然被问到汉诺塔递归算法是怎么实现的?然后重新理解了一遍汉诺塔算法,记录下来。
汉诺塔递归算法的由来:
在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候,
在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔。不论白天黑夜,
总有一个僧侣在按照下面的法则移动这些金片:
一次只移动一片,不管在哪根针上,小片必须在大片上面。僧侣们预言,
当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭,
而梵塔、庙宇和众生也都将同归于尽。
简单描述:
有三个柱子A , B , C 其中A柱子上放有n个盘子,并且从底部到顶部盘子由大到小排列。现在要将A柱子上的盘子全部转移到C柱子上面。
移动规则:
(1) 每次只能移动一个盘子,
(2)每次移动必须保证三根柱子上大盘子在下、小盘子在上。
算法推理:
如果n是1的时候 只需要直接放到C上即可。A --> C
如果n是2的时候 则需要A --> B,A-->C,B-->C
如果n是3的时候 则需要A --> C,
A-->B,
C-->B(n-1个盘子移动到B上),
A-->C(第n个盘子移动到C上),
B-->A,
B-->C,
A-->C;(n-1个盘子移动到C上)
那么我们可以看到动的过程是这样的:
(1)先将n-1个盘子移动到B上,
(2)在将盘子n移动到C上,
(3)最后将n-1个盘子移动到C上。
好知道了上面的原理 那么我们开始上代码了
public class Tower {
public static void movePlate(int N,String A,String B,String C){
if(N==1){
printPath(A+"-->"+C);//n==1的时候A --> C
}else{
//先将n-1 个盘子先移动到 B
movePlate(N-1,A,C,B);
//先将A第n个盘子移动到 C
printPath(A+"-->"+C);//最后一步A --> C
//先将B第n-1个盘子移动到 C
movePlate(N-1,B,A,C);
}
}
public static void printPath(String movePath){
System.out.println(movePath);
}
public static void main(String[] args) {
movePlate(3,"A","B","C");
}
}
打印结果:
A-->C
A-->B
C-->B
A-->C
B-->A
B-->C
A-->C
是不是已经清楚了,汉诺塔算法就是这么简单。
那么回到故事上面N == 64 的时候需要多少步呢?
我们发现移动步数是1,3,7,15,31,.....
f(n)=2*f(n-1)+1 n-1个盘子有A-->B 一次A-->C 最后n-1个盘子由b-->C
推导得出:N个盘子需要2^N-1次 那么N=64时就为2^64-1=18446744073709551615次(18亿亿)
一秒一次搬运的话 需要5845.54亿年 所以世界末日到来还是很遥远的。哈哈哈。。。