64,649
社区成员
发帖
与我相关
我的任务
分享
一位美国学者发现一种出人意料的方法,只要轮流进行两步操作就可以了。
首先把三根柱子按顺序排成品字型,把所有的圆盘按从大到小的顺序放在柱子A上。
根据圆盘的数量确定柱子的排放顺序:若n为偶数,按顺时针方向依次摆放 A B C;
若n为奇数,按顺时针方向依次摆放 A C B。
(1)按顺时针方向把圆盘1从现在的柱子移动到下一根柱子,即当n为偶数时,若圆盘1在柱子A,则把它移动到B;若圆盘1在柱子B,则把它移动到C;若圆盘1在柱子C,则把它移动到A。
(2)接着,把另外两根柱子上可以移动的圆盘移动到新的柱子上。即把非空柱子上的圆盘移动到空柱子上,当两根柱子都非空时,移动较小的圆盘(这一步没有明确规定移动哪个圆盘,你可能以为会有多 种可能性,其实不然,可实施的行动是唯一的)。
(3)反复进行(1)(2)操作,最后就能按规定完成汉诺塔的移动。
程序设计思想:
(1)将盘子标号为1,2,3......; 1 代表最小的盘子;
三根柱子分别为top[0]、top[1]、top[2]
将柱子标号为top[0]、top[1]、top[2]有利于盘子的顺序移动。用LowTray记录最小盘子(1号)所在柱子的标号。
1>、TrayAmount(盘子总数)为偶数时,将1号盘子由top[LowTray]移动到top[sub] sub = (LowTray + 1) % 3
(TrayAmount(盘子总数)为奇数时,将1号盘子由top[LowTray]移动到top[sub] sub = (LowTray + 2) % 3 )
2>、把另外两根柱子上可以移动的圆盘移动到新的柱子上。我将top[0]、top[1]、top[2]栈尾值设为65(top->tray = 65),这样可以通过比较两个栈顶元的大小来决定移动哪一个盘子 (移动较小的圆盘)。
3>、当top[0]、top[1]上没有盘子时停止
(2)输出格式:Move tray 1 : 0-->2 表示将盘子 1 从top[0]移动到top[2]
源程序:
/*
*hanoi塔问题;用非递归实现
*将盘子标号为1,2,3......; 1 代表最小的盘子;
*三根柱子分别为top[0]、top[1]、top[2]
*/
#include<stdio.h>
#include<malloc.h>
typedef int ElemType;
typedef struct stack
{
ElemType tray;
struct stack *next;
}stack;
stack *top[3];
//TrayAmount盘子总数;LowTray是最小盘子(1号)所在柱子的标号
/*
*功能:建立空栈
*返回:栈顶指针
*/
stack *CreateStack()
{
stack *top;
top = (stack *)malloc(sizeof (stack));
top->tray = 65;
top->next = NULL;
return(top);
}
/*
*功能:进栈
*参数:进栈无素,栈顶指针
*返回:栈顶指针
*/
stack *push(int e, stack *top)
{
stack *p;
p = top;
top = (stack *)malloc(sizeof (stack));
top->next = p;
top->tray = e;
return(top);
}
/*
*功能:出栈
*参数:栈顶指针
*返回:栈顶指针
*/
stack *pop(stack *top)
{
stack *p;
p = top;
top = top->next;
free(p);
return(top);
}
/*
*功能:移动盘子并输出移动路径
*参数:盘子总数
*/
void hanoi(int TrayAmount)
{
int sub, n, i, LowTray = 0;
n = TrayAmount % 2;//TrayAmount为偶数时n = 0;TrayAmount为奇数时n = 1
while (!(top[0]->tray == 65 && top[1]->tray == 65))//当top[0]、top[1]上没有盘子时停止
{
i = LowTray;
sub = i + 1 + n;
sub = sub % 3;
top[sub] = push(top[i]->tray, top[sub]);//移动1号盘
top[i] = pop(top[i]);
printf("Move tray 1 :%d-->%d\n", i, sub);
sub = i + 2 - n;
sub = sub % 3;
if (top[i]->tray < top[sub]->tray)
{
top[sub] = push(top[i]->tray, top[sub]);
printf("Move tray %d :%d-->%d\n",top[i]->tray, i, sub);
top[i] = pop(top[i]);
}
else if (top[i]->tray > top[sub]->tray)
{
top[i] = push(top[sub]->tray, top[i]);
printf("Move tray %d :%d-->%d\n", top[i]->tray, sub, i);
top[sub] = pop(top[sub]);
}
LowTray = LowTray + n + 1;
LowTray = LowTray % 3;
}
}
void main()
{
int i = 0, TrayAmount;
top[0] = CreateStack();
top[1] = CreateStack();
top[2] = CreateStack();
printf("Enter TrayAmount:\nTrayAmount=");
scanf("%d", &TrayAmount);
for (i = TrayAmount; i > 0; i-- )//盘子都放在柱子0上
{
top[0] = push(i, top[0]);
}
hanoi(TrayAmount);
}
很久以前整理的,程序还可以优化,供参考