Java递归实现汉诺塔

汉诺塔问题[又称河内塔]是印度的一个古老的传说。

据传开天辟地之神勃拉玛在一个庙里留下了三根金刚石的棒,第一根上面套着64个圆的金片,最大的一个在底下,其余一个比一个小,依次叠上去,庙里的众僧不倦地把它们一个个地从这根棒搬到另一根棒上,规定可利用中间的一根棒作为帮助,但每次只能搬一个,而且大的不能放在小的上面。就是这看似简单的问题,却困扰了人们千年以上。

后来,这个传说就演变为汉诺塔游戏,玩法如下:

1.有三根杆子A,B,C。A杆上有若干盘子
2.每次移动一块盘子,小的只能叠在大的上面
3.把所有盘子从A杆全部移到C杆上

Java递归实现汉诺塔_第1张图片

佩服博客园一哥们的分析过程,很透彻。

我们直接假设有n个盘子:

  先把盘子从小到大标记为1、2、3……n

  先看原问题三个柱子的状态:

状态0:  A:按顺序堆放的n个盘子。B:空的。C:空的。

  目标是要把A上的n个盘子移动到C。因为必须大的在下小的在上,所以最终结果C盘上最下面的应该是标号为n的盘子,试想:

要取得A上的第n个盘子,就要把它上面的n-1个盘子拿开吧?拿开放在哪里呢?共有三个柱子:A显然不是、如果放在C上

了,那么最大的盘子就没地方放,问题还是没得到解决。所以选择B柱。当然,B上面也是按照大在下小在上的原则堆放的

(记住:先不要管具体如何移动,可以看成用一个函数完成移动,现在不用去考虑函数如何实现。这点很重要)。

  很明显:上一步完成后三个塔的状态:

状态1:   A:只有最大的一个盘子。B:有按规则堆放的n-1个盘子。C空的。

  上面的很好理解吧,好,其实到这里就已经完成一半了。(如果前面的没懂,请重看一遍。point:不要管如何移动!)

我们继续:

  这时候,可以直接把A上的最大盘移动到C盘,移动后的状态:

中间状态:  A:空的。B:n-1个盘子。C:有一个最大盘(第n个盘子)

  要注意的一点是:这时候的C柱其实可以看做是空的。因为剩下的所有盘子都比它小,它们中的任何一个都可以放在上面,也就是C柱上。

  所以现在三个柱子的状态:

中间状态:  A:空的。B:n-1个盘子。C:空的

  想一想,现在的问题和原问题有些相似之处了吧?如何更相似呢?显然,只要吧B上的n-1个盘子移动到A,待解决的问题和原问题就相比就只是规模变小了。

  现在考虑如何把B上的n-1个盘子移动到A上,其实移动方法和上文中的把n-1个盘从A移动到B是一样的,只是柱子的名称换了下而已。。(如果写成函数,只是参数调用顺序改变而已)。 

  假设你已经完成上一步了(同样的,不要考虑如何去移动,只要想着用一个函数实现就好),请看现在的状态:

状态2: A:有按顺序堆放的n-1个盘子。B:空的。C:按顺序堆放的第n盘子(可看为空柱)

就在刚才,我们完美的完成了一次递归。如果没看懂请从新看一遍,可以用笔画出三个状态、静下心来慢慢推理。

我一再强调的:当要把最大盘子上面的所有盘子移动到另一个空柱上时,不要关心具体如何移动,只用把它看做一个函数可以完成即可,不用关心函数的具体实现。如果你的思路纠结在这里,就很难继续深入了。

到这里,其实 基本思路已经理清了。状态2和状态0,除了规模变小 ,其它方面没有任何区别了。然后只要用相同的思维方式,就能往下深入。

好了,看看如何用算法实现吧:

定义函数hanoi(a,b,c,n)表示把a上的n个盘子移动到c上,其中可以用到b。

定义函数move(m,n)表示把m上的盘子移动到n上

我们需要解决的问题正是hanoi (a,b,c,n)   //上文中的状态0

1、把A上的n-1个移动到B:   hanoi (a,b,c,n-1); // 操作结束为状态1

2、把A上的大盘子移动到C:      move(a,c)    

3、把B上的n-1移动到A:    hanoi (b,a,c,n-1);  //操作结束位状态2(和状态1相比只是规模变小)

Java实现

public class Hanoi {

    public static void main(String[] args) {
        hanoi('a','b','c',3);
    }

    /**
     * @param n  盘子数
     * @param a  源座
     * @param b  辅助座
     * @param c  目标座
     */
    public static void hanoi(char a,char b,char c,int n) {
        if(n==1){
            System.out.printf("Move disk %d from %c to %c\n",n,a,c);
        }else{
            hanoi(a,b,c,n-1);
            System.out.printf("Move disk %d from %c to %c\n",n,a,c);
            hanoi(b,a,c,n-1);
        }

    }
}

参考博客
Hanoi Tower 汉诺塔的简单分析/C
Java汉诺塔算法

你可能感兴趣的:(Java)