(优秀汉诺塔算法)对汉诺塔经典递归问题的理解与讲解(部分引用大神代码,附链接。)
来源:互联网 发布:ubuntu卡在登陆界面 编辑:程序博客网 时间:2024/05/13 18:26
博客大神的优秀汉诺塔代码:喜欢特别冷的冬天下着雪 (侵权联系)
本文只是在大神思路的基础上加以理解。
- #include <stdio.h>
- //第一个塔为初始塔,中间的塔为借用塔,最后一个塔为目标塔
- int i=1;//记录步数
- void move(int n,char from,char to) //将编号为n的盘子由from移动到to
- {printf("第%d步:将%d号盘子%c---->%c\n",i++,n,from,to);
- }
- void hanoi(int n,char from,char denpend_on,char to)//将n个盘子由初始塔移动到目标塔(利用借用塔)
- {
- if (n==1)
- move(1,from,to);//只有一个盘子是直接将初塔上的盘子移动到目的地
- else
- {
- hanoi(n-1,from,to,denpend_on);//先将初始塔的前n-1个盘子借助目的塔移动到借用塔上
- move(n,from,to); //将剩下的一个盘子移动到目的塔上
- hanoi(n-1,denpend_on,from,to);//最后将借用塔上的n-1个盘子移动到目的塔上
- }
- }
- void main()
- {
- printf("请输入盘子的个数:\n");
- int n;
- scanf("%d",&n);
- char x='A',y='B',z='C';
- printf("盘子移动情况如下:\n");
- hanoi(n,x,y,z);
- }
大神的代码很简明,即涉及到了计数,又完美的凸显了整个过程细节,但是对于部分人快速理解来说有些困难。
在递归的过程中,重点在于对第n步与第n-1步之间的关系分析,最基本的就是数学关系:例如f(n)=f(n-1)+f(n-2)、f(n)=f(n-1)*m;
确定了准确的递归关系之后,就需要我们根据程序功能来设定基本值了:例如Fibonacci 就可设置 f(1)=0,f(2)=1;再使用if 等语句来判断条件的达到,从而终止递归,返回上层函数,最后返回答案。
!递归问题中,在具体的两步之间研究出其中的规律就能递归下去!
在汉诺塔中,基本的数学关系特别简单,就是将第n个(此处假设越往下盘子号数越大)盘子放到目的塔之前,要将上面的n-1个盘子先放到借用塔(步骤1)上,将第n个盘子放到目的塔上(步骤2)后,再将这n-1个盘子从借用塔放到目的塔(步骤3);
当移动次数用函数fun(n)表示时 其中,数量关系是:
步骤1与步骤3移动次数其实是一样的,因为都是移动n-1个盘子到另外一个塔上。
而步骤2只需要一次移动;
所以:f(n)=2*f(n-1)+1;
但是,如果需要明确的看清每一次移动是怎么做到的就必须输出每一步的移动过程,这不是知道简单的数学关系就能解决的,
这里就需要用到,汉诺塔问题递归中存在的另外一种关系:
三座塔:初始塔。目的塔。借用塔的身份转换关系:
具体到f(n)初始塔 是 A 目的塔是C 借用塔是B
对于步骤1:进入到f(n-1) 此时的初始塔依旧是A 但 目的塔变为 B 借用塔变为 C (不太清楚的话 画画图)
因此这里的递归变化在于 目的塔与借用塔身份互换。
对于步骤2:不需要借用塔, 原来的目的塔与初始塔也无变化。
对于步骤3:进入到f(n-1) ' 此时的初始塔变为B 但 目的塔变为C 借用塔变为 A (不太清楚的话 画画图)
因此这里的递归变化在于 上面所述的变化。
对于之后的每一次简化递归 上层函数对他下面的函数来说 都是这种塔的身份变换。
因此,我们可以利用这种塔的变换来进行输出中的调用,将三个塔柱命名,通过传参,将每一步正确的移动细节输出。
- void move(int n,char from,char to) //将编号为n的盘子由from移动到to
- {printf("第%d步:将%d号盘子%c---->%c\n",i++,n,from,to);
- }
去掉那层输出后,就可以看做单纯的计数程序:
#include <stdio.h>
//第一个塔为初始塔,中间的塔为借用塔,最后一个塔为目标塔
int i=1;//记录步数
void move(int n) //将编号为n的盘子由from移动到to
{printf("第%d步",i++);
}
void hanoi(int n)//将n个盘子由初始塔移动到目标塔(利用借用塔)
{
if (n==1)
move(1);//只有一个盘子是直接将初塔上的盘子移动到目的地
else
{
hanoi(n-1);//先将初始塔的前n-1个盘子借助目的塔移动到借用塔上
move(n); //将剩下的一个盘子移动到目的塔上
hanoi(n-1);//最后将借用塔上的n-1个盘子移动到目的塔上
}
}
int main()
{
printf("请输入盘子的个数:\n");
int n;
scanf("%d",&n);
char x='A',y='B',z='C';
printf("盘子移动情况如下:\n");
hanoi(n);
return 0;
}
- (优秀汉诺塔算法)对汉诺塔经典递归问题的理解与讲解(部分引用大神代码,附链接。)
- 汉诺塔问题(经典递归算法)
- 递归经典算法 汉诺塔问题
- 对生成对抗网络GANs原理、实现过程、应用场景的理解(附代码),另附:深度学习大神文章列表
- 对多态的理解(附经典练习题)
- 对汉诺塔的递归理解
- 对递归算法的理解
- 原始的汉诺塔问题递归算法(java代码)
- 分割问题(对递归的理解)
- 《程序员的数学》:汉诺塔问题(Hanoi问题)的递归算法与非递归算法总结
- 汉诺塔问题(Hanoi问题)的递归算法与非递归算法详解
- K近邻算法讲解与python实现(附源码demo下载链接)
- 汉诺塔递归算法的理解
- 对 汉诺塔 经典递归的反思
- 经典递归算法,汉诺塔
- 汉诺塔算法(经典递归)
- 经典汉诺塔递归算法
- 递归算法与两个经典问题:汉诺塔问题和八皇后问题
- 自己写的常用库
- hdu 5387 Clock
- 1008
- Swift学习(JSON转Model)HandyJSON 的学习理解
- Drawable系列(三)——LayerDrawable的属性和使用介绍
- (优秀汉诺塔算法)对汉诺塔经典递归问题的理解与讲解(部分引用大神代码,附链接。)
- JQuery Validate-Validator对象
- Android中的PopupWindow详解
- 深入分析Android Binder 驱动
- 给未来程序员的15个顶级职业建议
- 开发环境搭建
- AChartEngine图表库之动态折线图(一条)
- js模拟群聊场景-聊天信息动态出现效果
- Ubuntu 16.04下配置Nginx HTTPS