汉诺塔问题讲解

已知其本质:递归,现在我们来看一下原理:

如果a只有一个,那么很容易知道,a->c;即可。如果像图中一样有三个,那么顺序就是[拿草稿本跟着画,如果你反应不过来的话]:(其中的n-1)a->c  a->b  c->b  a->c  b->a  b->c  a->c   【PS:如果有能力会做动画】

(到此为止,别再拿具体数字算了),我们来看,如果有n个盘子,那么就要把n-1个挪到b上面,现在我们假定:pos1:初始站    pos2:中转站     pos3:目的站

这一步就是pos1->pos3,pos2作为中转站(汉诺塔就是hanoi(n-1,pos1,pos2,pos3);  );现在pos2上面有n-1给盘子所以就把pos2给移到pos3上面,pos1作为中转站(hanoi(n-1,pos2,pos1,pos3); )。

现在我明白你的新问题:不是只能移动一个盘子嘛?怎么解释的是n-1个盘子的移动呢?

请先认识一个客观解释,打印数字与搬运盘子是联动的,盘子数在函数内部不断被消减(或转移),消减(搬运)过程的显现就是看move的打印。

是这样的,n-1是不是具有任意性?【它可以代表任意的情况下,盘子的移动个数】,

1.函数的形参只是形参,与它所代表的实际意义不一样。比如:我的函数声明:void hanoi(int n,char pos1,char pos2,char pos3);但是实际代码里面又有: hanoi(2,pos1,pos3,pos2),显然我们只要看背后的逻辑含义就可以了

2.每一个目的站作为搬运成功的目的站,但同时也作为初始站。

3.move就是来打印轨迹的,并且在else语句的第一句里面,已经开始无限递归了,

因为 hanoi(2,pos1,pos3,pos2)作用只是把缩减后的盘子放到函数每一轮形参上默认的b(中转站),只是一开始写定了pos罢了此时的中转站作为初始站,在把每一轮缩减过后的盘子放到默认的目的站(pos3)上面,写成了hanoi(n-1,pos2,pos1,pos3); ,现在出现了一个奇妙的现象,pos3(已经放了2个盘子)刚好是n==3这条语句第一句实现完成的样子(pos3作为中转站),所以递归奇妙的循环了下来

带数字的落实过程:

无限递归的时候,n-1已经被缩减成了2再到1了,所以此时我们走进if,打印pos1->pos3(逻辑上的),然后回到n==2的情况,这下,hanoi(2,pos1,pos3,pos2);已经被走完了【这条语句代表把初始的盘子搬到中间了!!】,【接着n==2的情况下move会打印这个时候的起始到终点,但是move的pos3是Hanoi的pos2!!】此时,我们实现了n==2的情况下,把n=1的盘子搬到中转站上面,打印后走进hanoi(n-1,pos2,pos1,pos3);把n==2的盘子放到了pos3这次的目的站上面,相当于在n==3的前提下,上一轮目的站作为了这次的中转站。

技巧:递归里面套递归,在无限递归出来的时候,代码的状态应该是刚刚好走完这一条语句就能无缝衔接下一条语句,回到了在缩减n-1个规模的样子(的算法)(自己用自己的特点)

也就是说,递归需要满足的特点:上一层递归函数执行过后的代码状态刚好是这一轮走完当前语句的样子。

{个人感想:感觉和循环语句的书写方式差不多,只不过循环语句没有规模的缩减问题罢了。}

相关有关递归的工作原理浅谈,见我写的另一个博客:

链接指路:(84条消息) 递归过程与递归工作栈_薄荷糖yh的博客-CSDN博客

递归判断:发现可以用剥洋葱的办法解决这个问题(有递归边界)

代码段:

/*汉诺塔问题*/
#include<stdio.h>
//pos1:初始站	pos2:中转站 	pos3:目的站

void move(char pos1,char pos3);
void hanoi(int n,char pos1,char pos2,char pos3);

int main()
{
	int n=0;
	char pos1='a',pos2='b',pos3='c'; 
	printf("enter n:");
	scanf("%d",&n);
	hanoi(n,pos1,pos2,pos3);
	printf("\n");
}

void move(char pos1,char pos3)//显示一下,汉诺塔的搬运轨迹 
{
	printf("  %c->%c  ",pos1,pos3);
} 
void hanoi(int n,char pos1,char pos2,char pos3)
{
	if(n==1){
	move(pos1,pos3);
	}else{
	hanoi(n-1,pos1,pos3,pos2);//这一步的目的是把n-1个盘子移到b上,所以在这种情况下,pos2是目的站
	move(pos1,pos3); 
	hanoi(n-1,pos2,pos1,pos3);//还剩下的n-1给盘子在b上面,要通过a最终移到c上 
	}
	
}

代码效果:

来自b站的老师:感谢~C语言实现汉诺塔_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV13g41157wn/?spm_id_from=333.337.search-card.all.click&vd_source=be8749e14febdaca0f8bf10aa7fa346c

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值