递归 汉诺塔 问题 快点来个人吧 急死了 出事了

作者&投稿:平科 (若有异议请与网页底部的电邮联系)
为什么每次出事只报死了39个人~

39是个界限,超过了的话,相关部门的问责就上升一级


引用谭书第一版。

函数的递归调用

一个函数在它的函数体内调用它自身称为递归调用。 这种函数称为递归函数。C语言允许函数的递归调用。在递归调用中, 主调函数又是被调函数。执行递归函数将反复调用其自身。 每调用一次就进入新的一层。例如有函数f如下:
int f (int x)
{
int y;
z=f(y);
return z;
}
这个函数是一个递归函数。 但是运行该函数将无休止地调用其自身,这当然是不正确的。为了防止递归调用无终止地进行, 必须在函数内有终止递归调用的手段。常用的办法是加条件判断, 满足某种条件后就不再作递归调用,然后逐层返回。 下面举例说明递归调用的执行过程。

你这里的条件是if(n==1),就是A针上只有一个盘子,才结束调用函数,返回到上一个函数里,依次倒推。

Hanoi塔问题
一块板上有三根针,A,B,C。A针上套有64个大小不等的圆盘, 大的在下,小的在上。如图5.4所示。要把这64个圆盘从A针移动C针上,每次只能移动一个圆盘,移动可以借助B针进行。但在任何时候,任何针上的圆盘都必须保持大盘在下,小盘在上。求移动的步骤。
本题算法分析如下,设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上,见图5.5(b)。
(2)将A上的一个圆盘移到B,见图5.5(c)
(3)将C上的n`-1(等于1)个圆盘移到B,见图5.5(d)
B. 将A上的一个圆盘移到C,见图5.5(e)
C. 将B上的n-1(等于2,令其为n`)个圆盘移到C(借助A),
步骤如下:
(1)将B上的n`-1(等于1)个圆盘移到A,见图5.5(f)
(2)将B上的一个盘子移到C,见图5.5(g)
(3)将A上的n`-1(等于1)个圆盘移到C,见图5.5(h)。
到此,完成了三个圆盘的移动过程。
从上面分析可以看出,当n大于等于2时, 移动的过程可分解为
三个步骤:
第一步 把A上的n-1个圆盘移到B上;
第二步 把A上的一个圆盘移到C上;
第三步 把B上的n-1个圆盘移到C上;其中第一步和第三步是类同的。
当n=3时,第一步和第三步又分解为类同的三步,即把n`-1个圆盘从一个针移到另一个针上,这里的n`=n-1。 显然这是一个递归过
程,据此算法可编程如下:
move(int n,int x,int y,int z)
{
if(n==1)
printf("%c-->%c\n",x,z);
else
{
move(n-1,x,z,y);
printf("%c-->%c\n",x,z);
move(n-1,y,x,z);
}
}
main()
{
int h;
printf("\ninput number:\n");
scanf("%d",&h);
printf("the step to moving %2d diskes:\n",h);
move(h,'a','b','c');
}
move(int n,int x,int y,int z)
{
if(n==1)
printf("%-->%c\n",x,z);
else
{
move(n-1,x,z,y);
printf("%c-->%c\n",x,z);
move(n-1,y,x,z);
}
}
main()
{ ……
move(h,'a','b','c');
}
从程序中可以看出,move函数是一个递归函数,它有四个形参n,x,y,z。n表示圆盘数,x,y,z分别表示三根针。move 函数的功能是把x上的n个圆盘移动到z 上。当n==1时,直接把x上的圆盘移至z上,输出x→z。如n!=1则分为三步:递归调用move函数,把n-1个圆盘从x移到y;输出x→z;递归调用move函数,把n-1个圆盘从y移到z。在递归调用过程中n=n-1,故n的值逐次递减,最后n=1时,终止递归,逐层返回。当n=4 时程序运行的结果为
input number:
4
the step to moving 4 diskes:
a→b
a→c
b→c
a→b
c→a
c→b
a→b
a→c
b→c
b→a
c→a
b→c
a→b
a→c
b→c

呵呵,这样不好理解的话,我们把变量换个名称吧。

void solve(int disks,int source,int temp,int destination)
{
if(disks==1)
printf("%d---->%d\n",source,destination);
else
solve(disks-1,source,destination,temp)
printf("%d-->%d\n",source,destination);
solve(disks-1,temp,source,destination)
}

disks表示圆盘的个数,source表示所有盘子原来在的那根柱子(第一根), 而destination表示要移动到目标的那根柱子(第三根),temp则表示第二根柱子,是用来临时存放圆盘的.

递归的过程不是分为三个小过程么?

1.从1号柱子source移动n-1个圆盘到2号柱子temp,用3号柱子做临时存放。

根据这句话的理解,可以写成这样
solve(disks-1,source,destination,temp)
为什么呢?
看函数声明吧~
void solve(int disks,int source,int temp,int destination)
前面说了,source表示原来盘子在的位置,temp表示临时存放盘子的位置,destination表示最终要移动到的位置。
那么对第一句话的意思,就可以写出:
solve(disks-1,source,destination,temp); //(*)
把disks-1个圆盘从原来的柱子1号位置,要先移动到2号柱子的位置上,所以2号柱子此时是做为最终要移动到的位置,而3号柱子是暂时存放的。所以这时候的(*)号语句中的temp是最终要移动到的位置。而destination作为临时存放的柱子.

2 从1号柱子移动最后一个圆盘到3号柱子上
那么很容易得出
printf("%d-----%d",source,destination);

3 从2号柱子移动n-1个圆盘到3号柱子,用1号柱子做临时存放.
那么也就是
solve(disks-1,temp,source,destination);
这时候,因为disks-1个圆盘在2号柱子上,所以暂时作为“原始柱子“,以1号柱子临时存放,1号柱子在开始时,就是source。而最终要移动到destination上去。
所以是这样写的

如果disks==1的时候,也就是说这时候只有一个盘。那么就可以直接的把盘子从source位置直接移动到destination位置上。不需要调用递归了。

首先你要理解递归,递归具体做的什么呢?递归就是把原来的任务分成几个更小的任务,而更小的任务可以直接解决或者跟原来的任务性质是差不多的,因此,函数会持续调用,直到所有的函数都可以解决基本问题。
h(int n,char one,char two,char three) ,象这个函数,它的作用是完成汗诺塔的工作,即把n个盘子从one到three,借用two,而这个任务我们可以分为3个小任务,什么呢?
首先确定基本情况,n==1时,直接移过去就是,函数表示为printf("%c-->%c\n",one,three); ,
然后我们可以先把n-1个盘子从one移动到two,借助three,用函数表示即h(int n-1,char one,char three,char two),
然后把第n个盘子移动到three,即printf("%c-->%c\n",one,three); ,
最后我们把n-1个盘子从two移动到three,借助one,即(int n-1,char two,char one,char three),
这样,就用3个小任务完成了整个大任务。

这样讲不知你会否理解:
每遇到一个H(x,y,z,r)都会开一个空间给这个函数,既虽然反复的用一个函数,但是每一个函数都是不同的。
当函数结束完了后,这个空间就会收回。
所以第一个H最后才收回。

n,A,B,C在每一个函数中都是不同的,你不防用ai,Ai,Bi,C表示第i次遇到H,第i次把数据传进入,这样就清楚了。

建议你抽像理解.先找人把上面的n-1个由A移到B,自己把第n个的从A移到C,再找人把B上的n-1个从B移到C


鹿邑县14722658627: 递归 汉诺塔 问题 快点来个人吧 急死了 出事了 -
芮码恩氟: 引用谭书第一版.函数的递归调用 一个函数在它的函数体内调用它自身称为递归调用. 这种函数称为递归函数.C语言允许函数的递归调用.在递归调用中, 主调函数又是被调函数.执行递归函数将反复调用其自身. 每调用一次就进入新的...

鹿邑县14722658627: 递归 汉诺塔有些问题只能用递归来解决.一个典型的例子就是汉诺塔问题.问题的提法是:“传说婆罗门庙里有一个塔台,台上有3根标号为A,B,C的用钻石... -
芮码恩氟:[答案] void hanoi ( int n, char a, char b, char c ) { if ( n >= 1 ) { hanoi ( n-1, a, c, b ) ; printf(“%c --> %c\n”, a , c) ; hanoi ( n-1, b, a, c ) ; ...

鹿邑县14722658627: c语言递归解决汉诺塔参数变化的疑惑 -
芮码恩氟: 递归,要把n个从a移动到c(从第一个参数移动的第三个参数),就得把(n-1)个从a移动到b,把第n从a自动到c,再把(n-1)个从b移动到c,可以用递归的办法,只需改变参数的顺序就可以不用重新定义函数了.注意,函数的作用是把(n-1...

鹿邑县14722658627: 求汉诺塔C递归算法详细解答 -
芮码恩氟: Hanoi塔问题, 算法分析如下,设A上有n个盘子.如果n=1,则将圆盘从A直接移动到C.如果n=2,则:(1)将A上的n-1(等于1)个圆盘移到B上;(2)再将A上的一个圆盘移到C上;(3)最后将B上的n-1(等于1)个圆盘移到C上.如果n=...

鹿邑县14722658627: 汉诺塔问题 -
芮码恩氟: n=2^t-1(n为次数,t为碟子数) 有四个碟子 所以n=2^4-1=15 选B 汉诺塔(又称河内塔)问题是印度的一个古老的传说.开天辟地的神勃拉玛在一个庙里留下了三根金刚石的棒,第一根上面套着64个圆的金片,最大的一个在底下,其余一个比一个...

鹿邑县14722658627: 用函数递归解决汉诺塔问题,有三个底座A、B、C,A座上有n个盘子?
芮码恩氟: #include void move(char x,char y){ printf("%c-->%c ",x,y);}void hanoi(int n,char one,char two,char three)//将n个盘子从one座借助two座,移动到three座{ if(n==1) move(one...

鹿邑县14722658627: 解释下递归求汉诺塔问题 -
芮码恩氟: 递归法是一种很方便的算法,你不要太过于纠结过程 hannoi这个函数4个变量,分别是要处理的塔的层数n,和塔a,b,c; a表示原塔,b是目标塔,c是中间的塔; 当n=1时,只有一层,直接移动; 其余情况:先讲上面的(n-1)层塔移到c上,此处可看做原问题的子问题,即hanoi(n-1,a,c,b); 再将最底层移到b,即可.

鹿邑县14722658627: 什么是汉诺塔 如何利用递归调用 -
芮码恩氟: 汉诺塔(又称河内塔)问题是印度的一个古老的传说.开天辟地的神勃拉玛在一个庙里留下了三根金刚石的棒,第一根上面套着64个圆的金片,最大的一个在底下,其余一个比一个小,依次叠上去,庙里的众僧不倦地把它们一个个地从这根棒搬...

鹿邑县14722658627: 汉诺塔问题具体是怎么递归的?? -
芮码恩氟: 有a,b,c三个柱子hanoit(n-1,a,c,b);//先借助c,把上面n-1个从a移动到bmove(a,c);//把第n个从a移动到chanoit(n-1,b,a,c);//把上面n-1个从b移动到c 移动第n个要先移动前n-1个.

鹿邑县14722658627: 汉诺塔问题思路
芮码恩氟: 汉诺塔这个问题,在考虑它递归的时候,别想着我们真实移动的步骤,我当时也总是觉得很乱.你要这样考虑: 1, 2, 3 最初都在1上,最后要移动到3上.所以把除了最后一块都移动到2上,最后一块移动到3上,再把2的都移动到3上.这个过程...

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网