【函数递归——汉诺塔和青蛙跳台阶问题】

💖 技术宅,拯救世界!

🎁作者:@ecember
🎁专栏:《从0开始——C语言》
🎁 对读者的话:相信奇迹的人本身和奇迹一样伟大

Alt


🌹感谢大家的点赞关注 🌹,如果有需要可以看我主页专栏哟💖


⚡1. 前言

生命中最快乐的事情是拼搏,而非成功,生命中最痛苦的是懒散,而非失败。大家好,这里是ecember。今天ecember为大家带来经典的汉诺塔问题青蛙跳台阶问题,相信这两个问题大家都或多或少听说过或者遇到过,别慌,今天ecember来让大家彻底搞懂这两个问题(以下结果均在vs2022中编译)。
在这里插入图片描述

⚡2. 汉诺塔问题

我们先来看看汉诺塔问题的具体题目。
在这里插入图片描述
初始A柱1个盘子
当初始A只有一个盘子时我们只需要将这一个盘子移动到C柱即可。因此我们完成1个盘子的汉诺塔问题总共需要1步:

<1> a->c

初始A柱2个盘子
当初始A柱两个盘子我们需要先将小盘子移动到B柱,然后再将大盘子移动到C柱,最后再将小盘子移到C柱即可。因此我们完成1个盘子的汉诺塔问题总共需要3步:

<1> a -> b
<2> a -> c
<3> b -> c

初始A柱3个盘子

我们假设初始A柱上只有三个盘子,那么我们该怎么移动才能保证游戏规则呢?下面给大家上动态图演示。
在这里插入图片描述

我们完成3个盘子的汉诺塔问题总共需要7步:

<1> a -> c
<2> a -> b
<3> c -> b
<4> a -> c
<5> b -> a
<6> b -> c
<7> a -> c

看到这里还没懂?没关系我们再来一组。当A柱上有4个盘子时。

在这里插入图片描述
完成4个盘子的汉诺塔问题总共需要15步。

<1> a -> b
<2> a -> c
<3> b -> c
<4> a -> b
<5> c -> a
<6> c -> b
<7> a -> b
<8> a -> c
<9> b -> c
<10> b -> a
<11> c -> a
<12> b -> c
<13> a -> b
<14> a -> c
<15> b -> c

我们总共分析了四步,相信已经有小伙伴已经发现汉诺塔问题本质上是个递归问题,我们假设有n个盘子,不难发现:

(1)无论我们有多少个盘子都要先把前(n-1)个盘子先递归地从A柱上移动到B柱上
(2)然后再将最大的盘子移动到C柱上
(3)最后再递归地将B柱上的盘子移动到C柱上

在这里插入图片描述
所以我们总的递归层数有2层,每层对应完成上述第一步和最后一步。我们再拿前四个盘子来分析一遍。
在这里插入图片描述
不难发现无论我们的步骤有多少步a->c始终在中间,这一步便对应了我们的第二大步骤:当A柱上还剩1个盘时,将其移到C柱。我们再来分析分析参数,既然我们要实现递归函数,参数有几个呢?参数肯定是四个a,b,c,盘子数,每递归一次(即每移动一次),盘子数减1,我们再来观察观察上述四个盘子的步骤,很容易就可以看出它们的规律,因为它们是基于递归实现的,我们就拿第二个来做文章,我们第一次递归就把盘子从a移到b,即hanoi(a, c, b, n - 1);,最后一步的递归同样从b移动到c,即 hanoi(b,a,c,n-1); 到这我们分析完毕,上代码:

int count = 0;
void hanoi(char a, char b, char c, int n)
{
	if (n == 1)
	{
		printf("%c -> %c\n", a, c);
		count++;
	}
	else
	{
		hanoi(a, c, b, n - 1);
		printf("%c -> %c\n", a, c);
		hanoi(b, a, c, n - 1);
		count++;
	}
}
int main()
{
	int n;
	printf("汉诺塔问题:现有三个柱子 A,B,C。\n");
	printf("请输入圆盘个数:");
	scanf("%d", &n);
	printf("\n");
	printf("当A上面圆盘个数为%d时", n);
	printf("具体实现细节为:\n");

	hanoi('a', 'b', 'c', n);
	printf("****************\n");
	printf("总移动次数为:%d\n", count);
	printf("****************\n");

	return 0;
}

这里我们借用一个全局变量用于记录移动次数。看看实现效果:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

⚡3. 青蛙跳台阶问题

有了汉诺塔问题的基础过后,我们再来看青蛙跳台阶问题就会简单的多了。
我们先来看看问题:给定一个n阶的台阶,青蛙一次只能挑一个或者两个,问有多少种跳法?
在这里插入图片描述
我们知道青蛙每次跳一次或两次,当台阶数n == 1时,青蛙只有一种跳法,当n == 2时青蛙有两种跳法,若有n个台阶,青蛙的跳法则由n-1步和n-2步决定,我们便有了递归地思路。

int jump(int n)
{
	if (n == 0)
	{
		return 0;
	}
	if (n == 1)
	{
		return 1;
	}
	else if (n == 2)
	{
		return 2;
	}
	else
	{
		return jump(n - 1) + jump(n - 2);
	}
}
int main()
{
	int n;
	printf("青蛙跳台阶问题:\n");
	printf("请输入台阶级数:");
	scanf("%d", &n);
	printf("\n");
	printf("当台阶级数为%d时\n", n);
	printf("****************************\n");
	printf("共有 %d 种方法能到达台阶顶部\n", jump(n));
	printf("****************************\n");

	return 0;
}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
致此,青蛙跳台阶问题圆满结束。

⚡4. 结语

到这,我们的 《函数递归——汉诺塔和青蛙跳台阶问题》 已经接近尾声了,后续我还会持续更新C语言相关内容,学习永无止境,就会永远只会留给有准备的人。希望我的博客对大家有所帮助,如果喜欢的可以 点赞+收藏哦,也随时欢迎大家在评论区及时指出我的错误。
在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

guaabd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值