1.汉诺塔问题描述:
有3根柱子A,B,C,A柱上有n个盘子,盘子的大小不等,大的盘子在下,小的盘子在上。
要求将A柱上的n个盘子移到C柱上,每次只能移动一个盘子。
在移动过程中,可以借助于任何一根柱子(A、B、C),但必须保证3根柱子上的盘子都是大的盘子在下,小的盘子在上。
2.源程序:
注:源程序中的x,y,z分别代表题目要求中的A,B,C,下面是递归和非递归算法
#include<stdio.h>
#define MAXSTACK 10 /* 栈的最大深度 */
int c = 1; /* 一个全局变量,表示目前移动的步数 */
struct hanoi { /* 存储汉诺塔的结构,包括盘的数目和三个盘的名称 */
int n;
char x, y, z;
};
void move(char x, int n, char y) /* 移动函数,表示把某个盘从某根针移动到另一根针 */
{
printf("%d. Move disk %d from %c to %c\n", c++, n, x, y);
}
///*把x柱上的n个盘子借助于y柱移到z柱上*/
void hanoi(int n, char x, char y, char z) /* 汉诺塔的递归算法 */
{
if (1 == n)
move(x, 1, z);
else {
hanoi(n - 1, x, z, y);// /*把x柱上的n-1个盘子借助于z柱移到y柱上*/
move(x, n, z);//把第n个盘子从x柱移动到z柱上
hanoi(n - 1, y, x, z);//递归,把y柱上的n-1个盘子借助于x柱移到z柱上
}
}
void push(struct hanoi *p, int top, char x, char y, char z,int n)
{
p[top+1].n = n - 1;
p[top+1].x = x;
p[top+1].y = y;
p[top+1].z = z;
}
void unreverse_hanoi(struct hanoi *p) /* 汉诺塔的非递归算法 */
{
int top = 0;
while (top >= 0) {
while (p[top].n > 1) { /* 向左走到尽头 */
push(p, top, p[top].x, p[top].z, p[top].y, p[top].n);
top++;
}
if (p[top].n == 1) { /* 叶子结点 */
move(p[top].x, 1, p[top].z);
top--;
}
if (top >= 0) { /* 向右走一步 */
move(p[top].x, p[top].n, p[top].z);
top--;
push(p, top, p[top+1].y, p[top+1].x, p[top+1].z, p[top+1].n);
top++;
}
}
}
int main(void)
{
int i;
struct hanoi p[MAXSTACK];
printf("reverse program:\n");
hanoi(3, 'x', 'y', 'z');
printf("unreverse program:\n");
c = 1;
p[0].n = 3;
p[0].x = 'x', p[0].y = 'y', p[0].z = 'z';
unreverse_hanoi(p);
return 0;
}
程序的运行结果如下所示:
reverse program:
1. Move disk 1 from x to z
2. Move disk 2 from x to y
3. Move disk 1 from z to y
4. Move disk 3 from x to z
5. Move disk 1 from y to x
6. Move disk 2 from y to z
7. Move disk 1 from x to z
unreverse program:
1. Move disk 1 from x to z
2. Move disk 2 from x to y
3. Move disk 1 from z to y
4. Move disk 3 from x to z
5. Move disk 1 from y to x
6. Move disk 2 from y to z
7. Move disk 1 from x to z
Press any key to continue
3.起源:
汉诺塔是源自印度神话里的玩具。
如果移动一个圆盘需要1秒钟的话,等到64个圆盘全部重新落在一起,宇宙被毁灭是什么时候呢?
汉诺塔与宇宙寿命
让我们来考虑一下64个圆盘重新摞好需要移动多少次吧。1个的时候当然是1次,2个的时候是3次,3个的时候就用了7次......这实在是太累了
因此让我们逻辑性的思考一下吧。
4个的时候是
“3个圆盘重新摞在一起的次数”+1次+“3个圆盘重新摞在一起需要的次数”
=2x“3个圆盘重新摞在一起的次数”+1次
=15次。
那么,n个的时候是
2x“(n-1)个圆盘重新摞在一起的次数”+1次。
由于1 个的时候是1次,结果n个的时候为(2的n次方减1)次。
1个圆盘的时候 2的1次方减1
2个圆盘的时候 2的2次方减1
3个圆盘的时候 2的3次方减1
4个圆盘的时候 2的4次方减1
5个圆盘的时候 2的5次方减1
........
n个圆盘的时候 2的n次方减1
也就是说,n=64的时候是(2的64次方减1)次。
因此,如果移动一个圆盘需要1秒的话,
宇宙的寿命=2的64次方减1(秒)
2的64次方减1到底有多大呢?动动计算器,答案是一个二十位的数字:
18446744073709551615!
用一年=60秒x60分x24小时x365天来算的话,大约有5800亿年吧。
据说,现在的宇宙年龄大约是150亿年,还差得远呢。
汉诺塔问题在数学界有很高的研究价值,
而且至今还在被一些数学家们所研究,