汉诺塔问题(Hanoi Tower problem):有三根杆子A、B、C,A杆上串有上小下大若干碟子。每次移动一块碟子,在确保小碟子只能叠在大碟子上面的条件下,利用B过渡,请把所有碟子从A杆移到C杆上。
本问题充分体现使用递归法的2条实践准则:
1、设计优先。简洁而清晰的程序设计优先。汉诺塔问题的递归算法简短优雅,但是递归算法效率极其低下。碟子数为N时需要移动2N-1次,是算法中指数复杂度的典型例子。
2、效率平衡。如果可能,改进为迭代(Scheme中编写尾递归,Java中采用循环语句)。
解答:
结束条件: A杆上只有一个碟子,将它移到C。
递归式:
1、将上面的n-1个碟子从出发地A移到中转站B;
2、将第n个碟子移到目的地C;
3、将n-1个碟子从中转站B移到目的地C。package algorithm.recursion;
public class HanoiTower{
private static int step= 0;
/**汉诺塔的递归演示。
* @param from 碟子的出发地
* @param temp 碟子的中转站
* @param to 碟子的到达地
* @param n 要移动的碟子个数
*/
static void hanoi(char from, char temp, char to, int n){
if (n == 1) {
step++;
System.out.println("第"+step+ "步: "+ from+"→"+ to);
}else {
//将n-1个碟子移到中转站,故目前的到达地是temp。
hanoi(from, to,temp,n-1);
//第n个碟子移到到达地
step++;
System.out.println("第"+step+ "步: "+ from+"→"+ to);
//将n-1个碟子移到到达地。
hanoi(temp,from,to,n-1);
}
}
}
static void move(int n){
System.out.println("将移动"+n+"个盘子");
step= 0;
hanoi('a', 'b','c', n);
}
move(3)的输出:
将移动3个盘子
第1步: a→c
第2步: a→b
第3步: c→b
第4步: a→c
第5步: b→a
第6步: b→c
第7步: a→c