郁闷ing!想了一整天也没有结果的汉诺塔问题..

pestpatrol 2006-04-27 08:05:12
算法我已经弄的很明白了...标注在源程序中
可就是看不懂源程序(函数的递归调用)
这段程序到底怎么走的哩?
我是这么想的~
程序首先从main()开始执行起
输入n变量的值为3
调用movedisk()函数 传入盘子数 n 以及A,B,C(三个针的代表符号)三个变量实参数
分别传给了movedisk()函数中的n A B C四个形参
步骤如下:
n=3; n>1所以调用自己 movedisk(n-1,A,C,B);[形式参数中的值依次变为了2 A C B]
n=2; n>1所以再一次调用自己 movedisk(n-1,A,C,B); [形式参数中的值依次变为了1 A B C]
n==1 所以执行

else
printf("Move disk 1 from post %c to post %c.\n",A,C);
即输出结果为 Move disk 1 from post A to post C
然后程序还怎么走里?偶觉得程序就结束拉。。。

#include<stdio.h>
movedisk(int n,char A,char B,char C)
{
if(n>1){
movedisk(n-1,A,C,B);/*1.将n-1个盘从A通过C移动到B*/
printf("Move disk %d from post %c to post %c.\n",n,A,C);
movedisk(n-1,B,A,C);/*3.再将n-1个盘从B通过A移动到C*/
}
else
printf("Move disk 1 from post %c to post %c.\n",A,C);
/*2.n==1 将A上的一个盘移动到C*/
}
main()
{
int n;
char A='A',B='B',C='C';
printf("Please input a digit of disk first:\n");
scanf("%d",&n);
movedisk(n,A,B,C);
}

...全文
415 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
zcjblueice 2006-05-06
  • 打赏
  • 举报
回复
我觉得不要解释的那么复杂,刚开始我也不明白,如果有几十个盘子要顺着正常的思路一个个的去想,那爱因斯坦估计能想通了,其实定义写的最简单了,子程序或子函数反复的调用自己,并传入不同的变量来执行的程序设计技巧。一般来讲,里面传递的参数一般都是递增或递减的,但是要注意有个递归结束条件。找个递归阶乘看看就好了,但是我想你的问题是看不懂汉诺塔问题的源代码,这中间和一般的递归一次到就n-1不同,涉及到两次搬动,才能转到hano(from,to,auxiliary,n-1)上,先是目的和辅助交换,然后来源和辅助交换,我看数据结构的时候一开始也看不明白这个地方,呵呵,我也可以发个帖子帮助别人了。
zhangwanlong 2006-05-06
  • 打赏
  • 举报
回复
高中课改的数学的练习册有这道题
caiyujie87 2006-05-06
  • 打赏
  • 举报
回复
up
zhiguo_he 2006-05-04
  • 打赏
  • 举报
回复
要把递归的部分看成整体,想多了会晕的
chenhu_doc 2006-05-04
  • 打赏
  • 举报
回复
以上贴的是 Hanoi塔问题 的解析
chenhu_doc 2006-05-04
  • 打赏
  • 举报
回复
Hanoi塔问题是一个典型的可用递归方法解决的问题(递归问题通常可转化为非递归问题)[2]。算法分析如下,设A上有n个盘子。
如果n=1,则将圆盘从A直接移动到C。
如果n=2,则:
(1)将A上的n-1(等于1)个圆盘移到B上;
(2)再将A上的一个圆盘移到C上;
(3)最后将B上的n-1(等于1)个圆盘移到C上。
如果n=3,则:
A)将A上的n-1(等于2,令其为n`)个圆盘移到B(借助于C),步骤如下:
(1)将A上的n`-1(等于1)个圆盘移到C上。
(2)将A上的一个圆盘移到B。
(3)将C上的n`-1(等于1)个圆盘移到B。
B)将A上的一个圆盘移到C。
C)将B上的n-1(等于2,令其为n`)个圆盘移到C(借助A),步骤如下:
(1)将B上的n`-1(等于1)个圆盘移到A。
(2)将B上的一个盘子移到C。
(3)将A上的n`-1(等于1)个圆盘移到C。到此,完成了三个圆盘的移动过程。

从上面分析可以看出,当n大于等于2时, 移动的过程可分解为三个步骤:第一步 把A上的n-1个圆盘移到B上;第二步 把A上的一个圆盘移到C上;第三步 把B上的n-1个圆盘移到C上;其中第一步和第三步是类同的。 当n=3时,第一步和第三步又分解为类同的三步,即把n`-1个圆盘从一个针移到另一个针上,这里的n`=n-1。


Hanoi塔问题中函数调用时系统所做工作

一个函数在运行期调用另一个函数时,在运行被调用函数之前,系统先完成3件事:

①将所有的实参、返回地址等信息传递给被调用函数保存。

②为被调用函数的局部变量分配存储区;

③将控制转移到被调用函数的入口。

从被调用函数返回调用函数前,系统也应完成3件事:

①保存被调用函数的结果;

②释放被调用函数的数据区;

③依照被调用函数保存的返回地址将控制转移到调用函数。

当有多个函数构成嵌套调用时,按照“后调用先返回”的原则(LIFO),上述函数之间的信息传递和控制转移必须通过“栈”来实现,即系统将整个程序运行时所需的数据空间安排在一个栈中,每当调用一个函数时,就为其在栈顶分配一个存储区,每当从一个函数退出时,就释放其存储区,因此当前运行函数的数据区必在栈顶。堆栈特点:LIFO,除非转移或中断,堆栈内容的存或取表现出线性表列的性质。正是如此,程序不要求跟踪当前进入堆栈的真实单元,而只要用一个具有自动递增或自动递减功能的堆栈计数器,便可正确指出最后一次信息在堆栈中存放的地址。

一个递归函数的运行过程类型于多个函数的嵌套调用,只是调用函数和被调用函数是同一个函数。因此,和每次调用相关的一个重要的概念是递归函数运行的“层次”。假设调用该递归函数的主函数为第0层,则从主函数调用递归函数为进入第1层;从第i层递归调用本函数为进入下一层,即i+1层。反之,退出第i层递归应返回至上一层,即i-1层。为了保证递归函数正确执行,系统需设立一个“递归工作栈”,作为整个递归函数运行期间使用的数据存储区。每一层递归所需信息构成一个“工作记录”,其中包括所有实参、所有局部变量以及上一层的返回地址。每进入一层递归,就产生一个新的工作记录压入栈顶。每退出一层递归,就从栈顶弹出一个工作记录,则当前执行层的工作记录必是递归工作栈栈顶的工作记录,称这个记录为“活动记录”,并称指示活动记录的栈顶指针为“当前环境指针”。
stonepeter 2006-04-28
  • 打赏
  • 举报
回复
要真正理解Hanio塔的问题是有个过程的。我给几个建议:
1、再去看看其他递归程序,比如说计算数字的递归函数(生小兔子问题,弗不拉奇数列问题,类比一下;
2、去看看关于STACK的内容,去深入体会一下;
3、动手画一下数值比较小的时候的移动情况,如果再有不明白,多画几次,包括画数值比较大的。
4、多花点时间,相信很快就可以明白了。
祝你好运!
yuanchuang 2006-04-28
  • 打赏
  • 举报
回复
楼上的说得很“玄乎”,但就是正解。
----------------
这两天一直在听张震鬼故事……
cihw2005 2006-04-28
  • 打赏
  • 举报
回复
楼上的说得很“玄乎”,但就是正解。
feny911 2006-04-28
  • 打赏
  • 举报
回复
楼上废话,也是正解。
递归和数学归纳法的发明有力地证明了天才和疯子的确只有一纸之隔。

言归正传,学递归别想太多,这东西越想多越想不明白。
回忆一下学过的数学归纳法,很相似的。(或者说刚好相反)
chinesegxf 2006-04-27
  • 打赏
  • 举报
回复
刚学都是不好理解的,过一年就理解了
sankt 2006-04-27
  • 打赏
  • 举报
回复
汗,怎么中文都是乱码...
sankt 2006-04-27
  • 打赏
  • 举报
回复
#include<stdio.h>
#include<stdlib.h>

void movedisk(int n,char A,char B,char C)
{
if(n>1)
{
movedisk(n-1,A,C,B);/*1.½«n-1¸öÅÌ´ÓAͨ¹ýCÒƶ¯µ½B*/
printf("Move disk %d from post %c to post %c.\n",n,A,C);
movedisk(n-1,B,A,C);/*3.ÔÙ½«n-1¸öÅÌ´ÓBͨ¹ýAÒƶ¯µ½C*/
}
else
printf("Move disk 1 from post %c to post %c.\n",A,C);
/*2.n==1 ½«AÉϵÄÒ»¸öÅÌÒƶ¯µ½C*/
}
int main()
{
int n;
char A='A',B='B',C='C';
printf("Please input a digit of disk first:\n");
scanf("%d",&n);
movedisk(n,A,B,C);

system("pause");
return 0;

}

程序没有错,可能是你输入的n太大了
我这里运行良好.


汉诺塔是个指数时间复杂度算法.

pestpatrol 2006-04-27
  • 打赏
  • 举报
回复
肯定有错!大家帮我找找我的思路哪里出了问题

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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