算法经典趣题:汉诺塔(Hanoi)问题

汉诺塔算法

汉诺塔问题时一个典型的递归算法问题,可以先从简单的3层汉诺塔入手。假设有ABC三根棒子,初始状态时,A棒上放着3个圆盘,将其移动到C棒上,可以用B棒暂时放置圆盘。并且规定一次只能移动一个圆盘,且圆盘在放到棒上时,大的只能放在小的下面。

使用递归思想,可以采用以下步骤来完成圆盘的移动:

(1)将A棒上的两个圆盘(圆盘1和圆盘2)移到B棒上;

(2)将A棒上剩下的一个圆盘移到C棒上;

(3)将B棒上的两个圆盘(圆盘1和圆盘2)移到C棒上,即移动完成。

这里第一步和第三步是移动多个圆盘的操作,可以采用递归的思想,仍然使用上述步骤来完成。

将上述解决问题的步骤加以推广,便可得到如下递归求解汉诺塔算法:

如果只有一个圆盘,则把该圆盘从A棒移动到C棒,完成移动。如果圆盘数量 n>1,移动圆盘的过程可分为三步:

(1)将A棒上的n-1个圆盘移到B棒上;

(2)将A棒上的1个圆盘移到C棒上;

(3)将B棒上的n-1个圆盘移到C棒上。

其中,移动n-1个圆盘的工作可以归结为递归运算。

    void hanoi(int n,char a,char b,char c){
        // 只有一个盘子的时候,从A棒移动到C棒即可
        if(n == 1){
            System.out.printf("第%d次移动:圆盘从%c棒移动到%c棒%n",++count,a,c);
        }else{
            // 当有n个盘子时,将n-1个盘子先从A棒上移到缓冲B棒上
            // 把A棒上剩下的1个圆盘移到终点C棒上
            // 然后再将这n-1个盘子从缓冲b棒上移到终点C棒上
            hanoi(n-1,a,c,b);
            hanoi(1,a,b,c);
            hanoi(n-1,b,a,c);
        }
    }

汉诺塔求解

public class HanoiTower {
    // 汉诺塔——典型的递归算法问题
    private static int count = 0;
    // n为盘子数量,a为起点,b为缓冲,c为终点
    public static void hanoi(int n,char a,char b,char c){
        // 只有一个盘子的时候,从A棒移动到C棒即可
        if(n == 1){
            System.out.printf("第%d次移动:圆盘从%c棒移动到%c棒%n",++count,a,c);
        }else{
            // 当有n个盘子时,将n-1个盘子先从A棒上移到缓冲B棒上
            // 把A棒上剩下的1个圆盘移到终点C棒上
            // 然后再将这n-1个盘子从缓冲b棒上移到终点C棒上
            hanoi(n-1,a,c,b);
            hanoi(1,a,b,c);
            hanoi(n-1,b,a,c);
        }
    }

    public static void main(String[] args) {
        System.out.println("***汉诺塔问题求解***");
        System.out.println("请输入汉诺塔圆盘的数量:");
        Scanner input = new Scanner(System.in);
        int n = input.nextInt();
        hanoi(n,'A','B','C');
        System.out.printf("求解完毕,总共需要%d步移动!",count);
    }
}

运行代码结果如下:

***汉诺塔问题求解***
请输入汉诺塔圆盘的数量:
3
第1次移动:圆盘从A棒移动到C棒
第2次移动:圆盘从A棒移动到B棒
第3次移动:圆盘从C棒移动到B棒
第4次移动:圆盘从A棒移动到C棒
第5次移动:圆盘从B棒移动到A棒
第6次移动:圆盘从B棒移动到C棒
第7次移动:圆盘从A棒移动到C棒
求解完毕,总共需要7步移动!

你可能感兴趣的:(算法与数据结构)