递归算法就是一个函数通过不断对自己的调用而求得最终结果的一种思维巧妙的算法.无论在哪种语言里,汉诺塔都是递归算法的经典题目.
1.题目简介
有三根相邻的柱子,左边的柱子上从下到上按金字塔状叠放着n个不同大小的圆盘,要把所有盘子一个一个移动到右边的柱子上,并且每次移动同一根柱子上都不能出现大的盘子在小的盘子上方.
2.逻辑分析
假设我们有一个方法move(n)已经实现n个盘子的移动,当我们想再实现n+1个盘子的移动时,该怎么做呢?
>>首先调用move(n),将n个盘子从左边移动到中间的柱子;
>>然后将第n+1个盘子从左边移动到右边的柱子;
>>最后调用move(n),将n个盘子从中间再移动到右边的柱子,即可完成.
按照上面三个步骤,我们可以一直向前推导,直到只有一个盘子时,我们将它移动到正确的位置即可.注意,我们在每次调用move(n)方法时用到的"柱子"的并不一样,因此move(n)方法还应该有两个参数:src柱子和dest柱子.
3.代码实现
public class Hanoi {
static int count = 0;
public void move(Column src, Column dest, int number) {
count++;
if (number > 1) {
Column transit = Column.values()[3 - src.ordinal() - dest.ordinal()];
int frontnumber = number - 1;
this.move(src, transit, frontnumber);
System.out.println(number + "号盘子从\t " + src + "\t移动到\t" + dest);
this.move(transit, dest, frontnumber);
} else {
System.out.println(1 + "号盘子从\t " + src + "\t移动到\t" + dest);
}
}
public static void main(String[] args) {
new Hanoi().move(Column.LEFT, Column.RIGHT, 3);
System.out.println("操作已完成,一共操作了" + count + "次.");
}
}
enum Column {
LEFT, MIDDLE, RIGHT
}
执行结果:
1号盘子从 LEFT 移动到 RIGHT
2号盘子从 LEFT 移动到 MIDDLE
1号盘子从 RIGHT 移动到 MIDDLE
3号盘子从 LEFT 移动到 RIGHT
1号盘子从 MIDDLE 移动到 LEFT
2号盘子从 MIDDLE 移动到 RIGHT
1号盘子从 LEFT 移动到 RIGHT
操作已完成,一共操作了7次.