汉诺塔问题

我在我的前几篇博客中谈到栈的数据结构,由于栈的先进后出的特点,使得她这中数据结构非常适合使用汉诺塔来解释,因为二者的操作原理一样。由此也衍生了针对汉诺塔的一些算法。其中一个就是三根柱子的汉诺塔的移动步骤问题。要求写出算法实现,给定初始的一根柱子上的圆盘个数,打印完成汉诺塔移动的实现步骤。

汉诺塔的原理

应该有许多同学对汉诺塔的规则都很了解,为了让部分不太了解汉诺塔的同学,这里我再详细地介绍一个汉诺塔的原理:假设有三根柱子分别为A B C,一开始A上有N个圆盘,从小到大、从上到下分别是1、2、3、4.....N-1、N,我们要把A上的N个圆盘全部移动到C上面,使得最后C上的圆盘的排列也是从小到大依次排下来,且每次移动梅根柱子最上面的一个圆盘。

思考:

那么要如何来解决这个问题呢?我相信大部分人都有一致的解决办法,若要把A上面的圆盘全部移动到C上,那么需要把N-1个圆盘按顺序落在B上,最后的第N个圆盘才可以直接从A移动到C上,从而完成第N个圆盘的移动。之后再把B上的N-2个圆盘移动到A上,再把B上剩下的最后一个圆盘,也就是第N-1个圆盘直接移到C上,这时就已经完成了最下面两个圆盘的移动。继续这样的移动直到完成游戏。

代码实现

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

我们先看代码实现,然后结合代码具体分析这样写的原因

package cn.csu;

public class HanioTest {
    /**
     *
     * @param n 柱子上需要移动圆盘的个数
     * @param A 柱子A
     * @param B 柱子B
     * @param C 柱子C
     */
    public 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);

    }

    /**
     * 把A最上面的圆盘移动到C上
     * @param A 柱子A
     * @param C 柱子C
     */
    public static void move(char A,char C){
        System.out.println(A + "-->"+C);

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

我们对着代码来分析一下:

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

接下来是汉诺塔实现的关键,即把A上所有的圆盘移动到C上,需要先把A最上面的n-1个圆盘移动到B上,于是有了hanoi(n-1,A,C,B)的递归操作,接下来只需要把A上剩下的最大的圆盘移到C上。

现在B上有n-1个圆盘,C有一个最大的圆盘,接下来把B上这n-1个圆盘也移动到C商,此时把B想象成为之前的A,有一堆待移动的圆盘,把A想象成之前的B,是空的柱子,这时我们把需要调用方式变为“hanoi(n-1,B,A,C)”就可以完成移动。这就是递归调用的思想所在了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值