问题描述
- 假设有3个分别命名为X、Y、Z的塔座
- 在塔座X上插有n个直径大小各不相同、依小到大编号为1,2,...,n的圆盘。
- 现要求将X轴上的n个圆盘移至塔座Z上并仍按同样顺序叠排
- 圆盘移动时必须遵循下列规则:
- 每次只能移动一个圆盘
- 圆盘可以插在X、Y、Z中的任一塔座上
- 任何时刻都不能将一个较大的圆盘压在较小的圆盘之上
算法思想
- 当n=1时
- 问题比较简单,只要将编号为1的圆盘从塔座X直接移至塔座Z上即可;
- 当n>1时
- 需利用塔座Y作辅助塔座,若能设法将压在编号为n的盘之上的n-1个圆盘从塔座X移至塔座Y上
- 然后将编号为n的圆盘从塔座X移至塔座Z上
- 最后再将塔座Y上的n-1个圆盘移至塔座Z上
- 而将n-1个圆盘移至塔座Z上又相当于一个新的汉诺塔问题,这一次是以X为辅助塔座
- 循环往复,总是以X和Y这两个为辅助塔座
- 简言之(参考链接)
- 首先以Z为辅助塔座将n-1个圆盘移动Y
- 将编号为n的圆盘移至塔座Z
- 再将剩余的n-1个圆盘移至塔座Z
C语言伪代码表示的算法
void hanoi(int n, char x, char y, char z){
// 将塔座x上按直径由小到大且自上而下编号为1至n的n个圆盘按规则搬到
// 塔座z上,y可用作辅助塔座
// 搬动操作move(x, n, z)可定义为(c是初值为0的全局变量,对搬动计数):
// printf("%i. Move disk % i from %c to %c\n", ++c, n, x, z);
if(n == 1)
move(x, 1, z); // 将编号为1的圆盘从x移到z
else{
hanoi(n-1, x, z, y); // 将x上编号为1至n-1的圆盘移到y, z作辅助塔
move(x, n, z); // 将编号为n的圆盘从x移到z
hanoi(n-1, y, x, z); // 将y上编号为1至n-1的圆盘移到z, x作辅助塔
}
}
Java
/**
* 汉诺塔算法实现
* @param n 圆盘的数量
* @param x X塔座
* @param y Y塔座
* @param z Z塔座
*/
public void hanoi (int n, char x, char y, char z) {
if (1 == n) {
move(x, 1, z);
} else {
hanoi(n-1, x, z, y);
move(x, n, z);
hanoi(n-1, y, x, z);
}
}
/**
* 打印出移动过程
* @param x X塔座
* @param n Y塔座
* @param z Z塔座
*/
public static final void move (char x, int n, char z) {
System.out.println("将编号为" + n + "的圆盘从" + x + "塔座放到" + z + "塔座");
}
@Test
public void testHanoi () {
hanoi (3, 'X', 'Y', 'Z');
}
将编号为1的圆盘从X塔座放到Z塔座
将编号为2的圆盘从X塔座放到Y塔座
将编号为1的圆盘从Z塔座放到Y塔座
将编号为3的圆盘从X塔座放到Z塔座
将编号为1的圆盘从Y塔座放到X塔座
将编号为2的圆盘从Y塔座放到Z塔座
将编号为1的圆盘从X塔座放到Z塔座
Python
def move(n, a, b, c):
if n == 1:
print a, '-->', c
else:
move(n-1, a, c, b)
print a, '-->', c
move(n-1, b, a, c)
move(3, 'A', 'B', 'C')
A --> C
A --> B
C --> B
A --> C
B --> A
B --> C
A --> C