[C语言]函数的递归调用之汉诺塔问题(你一定可以看懂的详细代码解释)
1.必须装备
①了解怎么玩
2.汉诺塔问题解决
①题目要求
一块板上有三根柱子A,B,C。A柱上套有n个大小不等的圆盘,大的在下,小的在上。要求把这n个圆盘从A柱移动到C柱上,每次只能移动一个圆盘,移动可以借助B柱进行,但在任何时候,任何柱子上的圆盘都必须保持大盘在上,小盘在上,输出移动的步骤。
②要求分析:
设A上有n个盘子,
n=1,直接将A移动到C上。
n=2,将A上的第一个圆盘先移动到B上,再将A上第二个圆盘移动到C上,最后将B上的移动到A上
其实可以看出,就是先将A最上的圆盘(n-1)个先移动到B上,在把下面的圆盘(即第n个)移动到C上,最后在将B上面的(n-1)移动到C上.理论存在,代码走起:
#include <stdio.h>
void hnt(int n,char a,char b,char c)
{
if(n==1)
{
printf("%c—>%c\n",a,c );
}
else
{
hnt(n-1,a,c,b);
printf("%c——>%c\n",a,c );
hnt(n-1,b,a,c);
}
}
int main(void)
{
int n;
printf("输入A柱子上面有多少圆盘:");
printf("\n");
scanf("%d",&n);
hnt(n,'A','B','C');
}
运行结果:
其实在汉诺塔中最难理解的就是函数的调用过程,到底是如何实现的:这里我们需要补充一个小知识:c语言内存组织结构:
由上面的图可以知道函数的调用是在栈里面进行的,那我们还需要知道栈的先进后出理论,就是先进去的最后出来。那么接下来我们只需要依照这个理论就可以了解汉诺塔到底是如何调用的了。
②调用逻辑
递归的入口是我们输入的数字n,递归的出口是n=1。
接下来我们就一步一步来走入代码,因为土豆哥语文能力不太行,后面会附上图片来解释的,嘻嘻!
①是n=3进入,a=A,b=B,c=C。
②然后进入判断:n不等于1,执行hnt(n-1,a,c,b);
,(此时n=3的情况进栈)
此时n=2,a=A,b=C,c=B 进入循环执行void hnt(int n,char a,char b,char c)
再进入判断:n不等于1,执行hnt(n-1,a,c,b);
,(此时n=2的情况进栈)
此时n=1,a=A,b=B,c=C,
再进入判断:n为1,执行printf("%c—>%c\n",a,c );
(n=1的情况入栈)
此时输出A——>C,然后==(n=1的情况出栈)==
执行printf("%c——>%c\n",a,c );
因为此时传的值是n=2,a=A,b=C,c=B,
所以输出A——>B;
然后执行hnt(n-1,b,a,c);
,此时传的值还是n=2,a=A,b=C,c=B,所以在此进入循环执行void hnt(int n,char a,char b,char c)
的时候,n=1,a=C,b=A,c=B,判断n=1,执行printf("%c—>%c\n",a,c );
,(n=1的情况入栈)
所以输出C——>B,(n=2的情况出栈)
然后继续执行printf("%c——>%c\n",a,c );
输出A——>C,
然后再执行hnt(n-1,b,a,c);
,此时n=3,a=A,b=B,c=C。
所以进入语句后变为n=2,a=B,b=A,c=C,(此时n=2的情况入栈)
继续进入函数判断,n不等于1,执行hnt(n-1,a,c,b);
再判断n=1,执行printf("%c—>%c\n",a,c );
(n=1的情况入栈)
输出B——>A,(n=1的情况出栈)
执行执行printf("%c——>%c\n",a,c );
输出B——>C,
然后执行hnt(n-1,b,a,c);
变成了n=1,a=A,b=B,c=C,(n=1入栈)
判断n=1,输出A——>C(n=1出栈)(n=2出栈)(n=3出栈);
循环结束:
图解如下:
感谢您能看到这里呀,如果有帮助的话,麻烦给土豆哥点个赞呀!!!如果我有解释不好的地方,欢迎在评论区下面留言呀,如果有不懂的地方,也可以给我私信呀,我每一条都会看的,欢迎关注微信公众号:土豆哥666,我们一起变得更好!!!