【数据结构】汉诺塔问题(丰富图解)

刚刚学习完了函数递归的相关知识,汉诺塔问题是经典的函数递归的相关应用。所以这篇文章打算围绕着汉诺塔问题来分享一下自己的学习体会。


汉诺塔问题是什么?

通俗的说,给你三根立柱,分别命名为A、B、C,在A上有数量为n的盘子,并且这些盘子以从下到上,从大到小的顺序放置,现在需要你将A上的盘子挪动到C上去,要求:每次只能挪动一个盘子,并且在挪动过程中必须保证盘子在立柱上始终以从下到上,从大到小的顺序放置。


解题思路如何构建?

在函数递归的学习中,我们知道运用递归的知识可以将一些复杂问题拆解成为一个个简单问题,那么汉诺塔就可以是一个复杂问题,那么我们只需要想最简单的情况,即假设只有两个圆盘,那么显而易见的解决方法就是:A->B,A->C,B->C,倘若此时增加圆盘数量为n,那么我们就可以将这n个盘子分为两部分,一部分是从1到(n-1),另一部分是最底下的一个盘子n,这两部分我们就可以看成是最简单的情况(两个盘子),而1到(n-1)我们也可以分化为两部分,即1到(n-2)为一部分,n-1为一部分,朋友们有没有发现此时我们就完成了函数递归了呢,我们已经将复杂的问题简单化了。

图一:表示的是将1到(n-1)看成一个盘子,将n看成一个盘子。

 图二:将1(1到(n-2))看成一个盘子,将n-1看成一个盘子。(递归思想

这里需要注意的是大家不要忽略了③中B的处理,即需要递归的不仅是从A到B,还有从B到A的递归,图中没有画出,但是思路是一样的。

 如此不管n为多少,我们都可以将n无限的分为两部分,这样一来只要我们知道汉诺塔最简单情况即两个盘子的情况如何解决就可以了,这也充分说明了函数递归的巧妙:复杂问题简单化


代码实现

#include<stdio.h>

void move(char m,char n)
{
	printf("%c->%c\n", m, n);
}

void hanoi(int n, char a, char b, char c)
{
	if (n == 1)
		move(a, c);
	else           
	{
		hanoi(n - 1, a, c, b);//ps①
		move(a, c);           //ps②     
		hanoi(n - 1, b, a, c);//ps③
	}//关于这里如果大家没看懂,我在后续说明中再做讲解。
}

int main()
{
	int num = 0;
	scanf_s("%d", &num);
	printf("盘子的数量为:%d\n", num);
	hanoi(num, 'A', 'B', 'C');
	return 0;
}

注意:实参A、B、C与形参a、b、c不同,大家不要搞混,a、b、c更多的可以理解为柱子顺序。

后续说明在这里:大家有没有发现在A->B中明显涉及到了复杂问题拆分,即将1到n-1看成一个盘子,所以需要第一个递归ps①,而ps②中并没有涉及到递归,大家结合图片就能知道了,而ps③涉及到的是在B->A时,与ps①同理,也是将复杂问题拆分,这里大家搞懂ps①的递归后,不妨尝试理解ps③,相信这样可以让你理解的更加深入。


总结

有时候可能更多的需要大家去画图并实操,仅仅看一两篇文章就能吃透不太现实,拒绝拿来主义,伙伴们,动起来💪💪💪

希望这篇文章可以对你有所帮助。

  • 19
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

樊梓慕

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

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

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

打赏作者

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

抵扣说明:

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

余额充值