怎么用循环实现汉诺塔程序

streamlv 2011-11-07 06:00:42
听说所有的递归程序都可用循环来实现,汉诺塔递归实现很容易,但我自己想不出怎么用循环来实现,另外我想知道,递归变成循环有没有一般性的方法的?
...全文
340 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
ouen333 2011-11-07
  • 打赏
  • 举报
回复
这个可以百度的把。
streamlv 2011-11-07
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 udbwcso 的回复:]
C/C++ code

一位美国学者发现一种出人意料的方法,只要轮流进行两步操作就可以了。
首先把三根柱子按顺序排成品字型,把所有的圆盘按从大到小的顺序放在柱子A上。
根据圆盘的数量确定柱子的排放顺序:若n为偶数,按顺时针方向依次摆放 A B C;
若n为奇数,按顺时针方向依次摆放 A C B。

(1)按顺时针方向把圆盘1从现在的柱子移动到下一根柱子,即当n为偶数时,若圆盘1在柱子……
[/Quote]
看来是没有一般性的方法啊
尘缘udbwcso 2011-11-07
  • 打赏
  • 举报
回复

一位美国学者发现一种出人意料的方法,只要轮流进行两步操作就可以了。
首先把三根柱子按顺序排成品字型,把所有的圆盘按从大到小的顺序放在柱子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);
}

很久以前整理的,程序还可以优化,供参考
streamlv 2011-11-07
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 jxlijunhao 的回复:]
你知道要循环的次数吗???所以你可能闲着蛋疼。
[/Quote]
我主要是想通过这个例子了解一下递归怎么变循环
  • 打赏
  • 举报
回复
你知道要循环的次数吗???所以你可能闲着蛋疼。
guide: 1、此程序汉诺塔程序(此代码用到递归,包括直接递归和间接递归(间接递归是用在了重复使用本程序那块)); 2、此程序的代码流程是,由main函数进入之后,先后调用的函数是由上至下定义的; 3、亲爱的朋友,请尊重偶的版权,你也会得到相应的尊重哦! 4、若此程序或代码有不足或不对的地方,还望得到指正! 5、循环虽然比递归算法快,但比较而言,递归更容易让人理解! purpose: 1、培养独立思考算法的能力,特别是递归时,用到的是数学中的数列,找到整个递归的最先出栈的函数,以及数列的第n项与第n-1项的关系就能用递归解决问题; 2、通过试数来推算自己的程序逻辑是否有beg,并找出修复之; 3、熟练一下结构体和链表的基本推理,尤其是插入和删除元素时指针的走向! function: 1、简易输出汉诺塔步骤(由哪根柱子移到哪根柱子); 2、详细输出汉诺塔步骤(在功能1基础上逐步输出每次移动之后的盘子分布); 3、二维详细输出汉诺塔步骤(在前2功能基础上逐步输出二维盘子分布图); 4、动态二维输出汉诺塔步骤(在前3功能基础上演示动态输出并提示下一步); 5、可重复使用本程序! 在VC++6.0中的输出结果是: --------------------------- ………… 开始移动: 第1次移动过程: A(1号盘)→B 此时灰原の盘子分布图: A柱子 B柱子 C柱子 ↓ ↓ ↓ 1层为空层 第2层: 2* 1* 请按任意键继续. . . 第2次移动过程: A(2号盘)→C 此时灰原の盘子分布图: A柱子 B柱子 C柱子 ↓ ↓ ↓ 1层为空层 第2层: 1* 2* 请按任意键继续. . . 第3次移动过程: B(1号盘)→C 此时灰原の盘子分布图: A柱子 B柱子 C柱子 ↓ ↓ ↓ 第1层: 1* 第2层: 2* 请按任意键继续. . . 请问您是否要继续重玩游戏,需要重玩请按“Y”,否则按“N”结束程序! ………… ---------------------------

64,649

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧