汉诺塔问题时一个典型的递归算法问题,可以先从简单的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步移动!