死磕算法第二弹附加篇——汉诺塔

汉诺塔

栈的数据结构非常适合汉诺塔来解释,因为二者的操作原理是一样的,由此也衍生了针对汉诺塔的依稀额算法。其中一个就是三根柱子的汉诺塔的移动步骤。

汉诺塔的移动原理

这里我们详细的介绍一个汉诺塔的移动原理,假设三根柱子分别是A、B、C,一开始A上有N个圆盘,从小到大、从上到下分别是1、2......N-1、N,我们要把A上的N个圆盘远不移动到C上面,而每次只能移动每根柱子上面的一个圆盘。

我们可以反过来考虑一下,若要把A上的圆盘全部移动到C上,那么需要把前N-1的盘子按照顺序落到B上了,最后的第N个圆盘才能够直接从A移动到C上,从而完成第N个圆盘的移动。之后把B的N-2个圆盘移动到A上,再把B上剩下的一个圆盘,也就是N-1个圆盘直接移动到C上,这是就已经完成最下面的两个圆盘的移动,继续这样的移动,直接就完成有洗。

汉诺塔的递归实现

上面的步骤在代码上使用递归是最好实现的,要使用递归,就要考虑到需要进行递归的部分是那部分。

public class Hanoi {
    private static int moveNum = 0;

    private static void hanoi(int n, char a, char b, char c) {
        if (n == 1) {
            //如果只有一个圆盘,只需要移动就好
            move(a, c);
            return;
        }
        //先把A上的n-1个元哦按移动到B上
        hanoi(n - 1, a, c, b);
        //把A上的最后一个圆盘移动到C上
        move(a, c);
        //接下来递归,把B上的n-1个圆柱移动到C上
        hanoi(n - 1, b, a, c);
    }

    private static void move(char a, char c) {
        moveNum++;
        System.out.println(a + "--->" + c);
    }

    public static void main(String[] args) {
        hanoi(3,'A','B','C');
        System.out.println(moveNum);
    }

}

hanoi函数的第1个参数就是柱子上需要移动的元哦按的个数,后三个参数分别为一根柱子的标识。首先当n为1时,需要移动的圆盘只有一个,直接把A上的圆盘移动到C上就可以了,同时代码结束,因为已经没有需要移动的圆盘了。

接下来就是实现汉诺塔实现的关键,即把A上的所有圆盘移动到C上,需要先把A最上面的n-1个圆盘移动到B上,于是有了“hanoi(n-1,a,c,b)”,就可以完成移动,这就是递归调用的思想所在了。

在递归调用中会继续执行该方法,改变参数的值,继续打印,这样每次调用会减少n的值,直到n最后变为1之后,结束递归调用,最终完成汉诺塔移动。

转变一下思想,就能够理解从B上移动n-1个圆盘到C上其实和从A上移动元哦按到C上是一样的。

posted @ 2018-03-27 20:34  Mr-cc  阅读(229)  评论(0编辑  收藏  举报