🚀write in front🚀
🔎大家好,我是gugugu。希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎
🆔本文由 gugugu 原创 CSDN首发🐒 如需转载还请通知⚠
📝个人主页:gugugu------CSDN博客
🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝
📣系列专栏:gugugu的精品博客——CSDN博客
✉️我们并非登上我们所选择的舞台,演出并非我们所选择的剧本📩
前言
递归是函数的一个重难点,进入递归的学习,两道经典递归题目肯定是少不了的,分别是汉诺塔问题和青蛙跳台阶问题,今天带来汉诺塔问题的分享,当然,难度较大,记得反复观看学习,hhh.
一、汉诺塔题目介绍
1、背景
汉诺塔问题是一个经典的问题。汉诺塔(Hanoi Tower),又称河内塔,源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。
2、规则
规定,任何时候,在小圆盘上都不能放大圆盘,且在三根柱子之间一次只能移动一个圆盘。
3、图像模型
大概就是这样子。
二、操作思路
64个盘子太复杂了,我们就化繁为简,从1个盘子往上面逐渐叠加来看看规律
另外,我们为了把三个盘子区分开,不妨分别命名为a,b,c ,便于描述
1、一个盘子
ok,很简单,直接从a移到c
记作:a->c
共一步
2、两个盘子
两个盘子的话就要复杂一丢丢,但仍然很简单
记作:a->b , a->c ,b->c
共3步
我相信两个盘子还是很好理解的吧
3、三个盘子
这就有点复杂了,但是相比64个盘子还是简单的多
想想怎么移动盘子
记作:a->c, a->b, c->b, a->c, b->a,b->c,a->c
共7步
……………………
后面就开始复杂了,我就不列举了,真的会把博主“CPU”干爆的啊!!!
- ok,通过上面三组例子,我们可以看到每一组共需要2n-1步,所以啊,想要靠脑子把64个盘子推完,是不现实滴!
- 那么,就要引入递归啦。
三、正式开始
1、浅浅分析一下
-
我们这样思考,假设有n个盘子,我们可以把这n个盘子看成两个部分组成,分别是最下面的一个盘子和上面的n-1个盘子。
-
那么这样有什么好处呢?
-
好处啊,大大的
-
我们就可以看成两个盘子,按照两个盘子的做法来操作。
-
对里面的n-1个盘子也是这样子分成两部分,进行操作
-
这样就可以把一个大问题化解成很多个小问题
-
也就形成了递归
2、代码看看
#include <stdio.h>
void move(char post1, char post2)
{
printf("%c->%c ", post1, post2);
}
void hanio(int n, char post1, char post2, char post3)
{
if (n > 1)
{
hanio(n - 1, post1, post3, post2);
move(post1, post3);
hanio(n - 1, post2, post1, post3);
}
else
{
move(post1, post3);
}
}
int main()
{
int n = 0;
scanf("%d", &n);
hanio(n, 'A', 'B', 'C');
return 0;
}
ok ,我们来分析分析代码
3、深入分析一下
a、首先主函数部分
-
创建变量接收,盘子的个数
-
写函数传参,三个盘子的编号也要传过去
b、汉诺塔函数部分
我们创建了4个形参,分别用来接收盘子的个数,和三个盘子的编号
注意:我们把第一个位置称作起始位置,第二个位置称作中转位置,第三个位置称作目的位置
也就是说,我们把盘子从起始位置经中转位置,运送到目的位置
move函数就比较好理解了,就是一个移动函数,把盘子从一个位置移动到另一个位置,就不做过多解释了,相信大家肯定能看懂
难在汉诺塔的实现,下面详细分析
- 这个递归的极限条件时n==1
- 当n1时,直接把盘子从post1移动到post3
== 千万要注意,post1不一定就是a,post3也不一定就是c(非常重要啊,博主当初理解这个花了很久啊,千万要三连啊) - 这里是因为,经过多次操作,在传参的时候不一定按照a,b,c的顺序进行传参,等下回举例讲解,别急
当n>1时,进入递推出去
- han(n-1,post1,post3,post2)
- 这句代码的意思就是把n-1个盘子从起始位置post1 ,经中转位置post3,移动到目的位置post2上
- 也就是把n-1个盘子从a移动到了b
- move(post1,post3)
- 这句代码就是把剩下的那个盘子,从a移动到c
- han(n-1,post2,post1,post3)
- 这句代码的意思是把n-1个盘子从起始位置post2,经中转位置post1,最后移动到post3上面去
- ok也就完成了!
四、举例分析
我们以n=3来进行解释
还是文字再梳理一遍吧,图还是有点乱qaq
- 首先,传递过去的是(3,a,b,c)
- 推出去得到了(2,a ,c,b)
- 继续推出去得到了(1,a,b,c)
- 递归达到极限条件
- 走出了第一步a->c
- 开始往回推
- 回推的时候n=2
- 是这一步(2,a,c,b)
- 轮到move步骤
- 于是走出了第二步a->b
- 下面到(1,c,a,b)
- 走出第三步c->b
- n=2就走完了
- 往回推到n=3,也就是(3,a,b,c)
- 轮到move步骤
- 于是走出第四步a->c
- 接下来,又来到(2,b,a,c)
- 继续递出去
- 来到(1,b,c,a)
- 于是走出第五步b->a
- 又推回去
- 来到(2,b,a,c)
- move步骤
- 于是走出第六步b->c
- 下面来到(1,a,b,c)
- 于是走出第七步a->c
总共是a->c, a->b, c->b, a->c, b->a,b->c,a->c
终于走完了,对一下答案,看看是不是和编译器结果一样
结果相同,说明对了
注:文字要配合图像去看,去分析,单独看一个很容易懵
ok,本期分享到这里就结束了
本期分享存在一定难度,需要反复观看,认真思考,多多举例,自主实践,才能掌握
加油!!!!
!!!!!!!!!!!来个 三连 吧!!!!!!!!!!!!
!!!!!!!!!!!!谢谢大家!!!!!!!!!!!!