c语言中的汉诺塔问题详解
汉诺塔问题是一个古典的数学问题,也是c语言学习中一个用递归方法解题的典型实例,我们先看一下原题。
相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置64个金盘。游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。
对于这样一个问题,我们第一印象就是十分的复杂,写出移动盘子的每一步似乎非常的困难,但我们可以利用下面的递归方法来解决。
首先分析,将n个盘子从A移动到C可以分解为三个步骤
(1)将A上的n-1个盘子借助C移动到B上;
(2)将A上剩下的一个盘子移到C上;
(3)将n-1个盘子从B移动到C上;
这对于写代码来说就变得十分简单了,但是依然很抽象,不过不要急,我们先把代码写出来再慢慢分析,
这是代码 其中hanoi函数有四个值,hano(n,A,B,C),代表着我们将盘子从A借助B移动到C上
#include <stdio.h>
void hanoi(int n,char X,char Y,char Z)//n个盘子在A上,借助B,移动到C上
{if(n==1)//如果A上只有一个盘子,直接移动到C上printf("%c-->%c\n",X,Z);else//一旦多余一个,则执行递归程序{hanoi(n-1,X,Z,Y);//将A上的n-1个盘子,借助C,移动到B上printf("%c--> %c\n",X,Z);//将A 上的最后一个盘子移动到C上hanoi(n-1,Y,X,Z);//将B上的n-1个盘子,借助A,移动到C上}
}int main()
{int n;printf("请输入盘子的总数:");scanf("%d",&n);hanoi(n,'A','B','C');return 0;
}
我第一次看到这里时,就被震撼到了,一个如此复杂的数学问题竟然可以通过短短二十几行代码来实现,可是里面对于hanio函数的反复调用却让我十分头疼,这是怎么实现的呢?
下面我们以n=3为例来详细的解释一遍,这里我们需要用到一点栈的概念,简单说就是每一次递归之前程序都会将现在的数据储存在栈中(从下往上存储),递归结束后会依次从上往下调出数据,之后程序就会返回到这个数据存储的地方向后继续执行,此时栈中的这一条数据也会消失。
当程序执行到第一个hanoi函数时,显然n!=1,执行else的部分,此时hanoi函数中的变量值为hanoi(3,A,B,C),在执行第8行语句之前,首先要将其存放到栈中。经过下一行的递归后,四个值变为hanoi(2,A,C,B)。
此时栈中的数据为
第一次 hanoi(2,A,C,B) |
初始 hanoi(3,A,B,C) |
再继续第二次运行else后的代码,得到下一组数值hanoi(1,A,B,C)并储存,
再运行时n=1,终于可以执行printf语句啦!
输出 A-->C
这时程序就要开始处理栈中的数据了,从上往下执行,将程序返回原处,赋值后执行下一行,此时函数值为hanoi(2,A,C ,B)
输出 A-->B
继续执行时又遇到了递归程序,这时再将此时的数据储存到栈中,重新开始执行一个hanoi函数,此时hanoi(1,C,A,B)n=1,那么执行if后的语句
输出C-->B
之后返回栈中的第一条数据处,往下执行,这个时候我们发现,第一次递归的hanoi函数到此结束,程序接着处理栈中最底下的数据,hanoi(3,A,B,C)。将程序返回到这里并执行下面的语句
输出 A-->C
下面一条又是递归啦,我们再重复上面的过程,储存数据再重新调用hanoi函数。调用后hanoi(2,B,A,C),依旧不满足n=1,再重复以上过程,得到hanoi(1,B,C,A)
此时栈中的数据为
hanoi(2,B,A,C) |
hanoi(3,A,B,C) |
现在n=1,输出B-->A。
返回栈中第一条数据处,往后执行
输出B-->C
递归得hanoi(1,A,B,C)
再输出A-->C 。
此时栈中的数据为
hanoi(2,B,A,C) |
hanoi(3,A,B,C) |
分别对应的两个数据位置都位于hanoi函数的这个位置
在返回时,都会结束程序,所以整个递归到此结束,让我们统计一下输出的结果
输出 A-->C
输出 A-->B
输出C-->B
输出A-->C
输出B-->A
输出B-->C
输出A-->C
这就是n=3时,整个程序的运行的结果了。
总结:汉诺塔程序本身是一个极其复杂的问题,通过递归,我们可以节省大量的代码,通过一个简短的程序来解决这个问题,但是这其中的逻辑是不可能被简化的,只是由计算机替我们执行了而已,所以彻底的了解整个程序是如何对于hanoi函数一次次的调用,虽然有一定的难度,有点难以理解,我认为是非常有必要的,这可以让我们对递归运算有一个更深刻的了解。以上是n=3的情况,较为简单,大家有能力的可以挑战一下给n赋更大的值,那样递归分析的难度也会同样暴增。
另外,如果想要统计移动次数的话,还可以增加一个全局变量来达到目的。
下面是代码
#include <stdio.h>
int i=0;//增加一个全局变量
void hanoi(int n,char X,char Y,char Z) //n个盘子在A上,借助B,移动到C上
{i++; //每次调用hanoi函数,i都会+1if(n==1) //如果A上只有一个盘子,直接移动到C上printf("%c-->%c\n",X,Z);else //一旦多余一个,则执行递归程序{hanoi(n-1,X,Z,Y); //将A上的n-1个盘子,借助C,移动到B上printf("%c--> %c\n",X,Z); //将A 上的最后一个盘子移动到C上hanoi(n-1,Y,X,Z); //将B上的n-1个盘子,借助A,移动到C上}
}int main()
{int n;printf("请输入盘子的总数:");scanf("%d",&n);hanoi(n,'A','B','C');printf("一共需要移动的次数为%d",i);return 0;
}
运行截图
c语言中的汉诺塔问题详解相关推荐
- 汉诺塔问题详解 递归实现 C语言
目录 一.前言 二.游戏规则 三.思路讲解 四.完整代码 五.最终结果展示 一.前言 汉诺塔:汉诺塔(Tower of Hanoi)源于印度传说中,大梵天创造世界时造了三根金钢石柱子, 其中一根柱子 ...
- Tower of Hanoi(汉诺塔)详解
一个经典的汉诺塔问题,带着我自己的理解给做这个问题的友友们解决一下,包括我本人在做的时候也遇到的一些问题给大家阐述一下.话不多说,来看: 汉诺塔 问题描述: 汉诺塔(Hanoi Tower),又称河内 ...
- QT汉诺塔项目详解:多线程动画
关注QT坐标,多线程动画中坐标的变化.汉诺塔都是吃要的. 我的汉诺塔新解:一种更美的描述. http://blog.csdn.net/weixin_39788534/article/details/7 ...
- python之汉诺塔问题详解
#汉诺塔问题 传说古老印度在一个圣庙里,一块黄铜板上插着三根宝石针.印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片圣庙,一块黄铜板上插着三根宝石针.印度教的主神梵 ...
- 算法 汉诺塔-java详解
第一次看到这个算法时,很懵逼,是在栈那里.想了半天没想到半点跟栈有关系的解法.最后看了答案,是用的递归.但是看了答案还是很懵逼,下面就是博主自己对汉诺塔的一些了解. 有三根木桩,第一根上有n个盘子,最 ...
- 走进递归经典——汉诺塔问题详解
目录 传统艺能
- c语言递归汉诺塔次数,c语言递归解决汉诺塔参数变化的疑惑
c语言递归解决汉诺塔参数变化的疑惑 答案:3 信息版本:手机版 解决时间 2020-04-05 14:20 已解决 2020-04-05 10:49 #include void main() {vo ...
- c语言递归解决汉诺塔问题
c语言递归解决汉诺塔问题 参考文章: (1)c语言递归解决汉诺塔问题 (2)https://www.cnblogs.com/didiaoxiaoguai/p/6686407.html 备忘一下.
- go语言字符串换行_Go语言中的字符串处理方法示例详解
1 概述 字符串,string,一串固定长度的字符连接起来的字符集合.Go语言的字符串是使用UTF-8编码的.UTF-8是Unicode的实现方式之一. Go语言原生支持字符串.使用双引号(" ...
最新文章
- 根据PI/4 = 1 - 1/3 +1/5-1/7+1/9求圆周率
- 智能车竞赛技术报告 | 智能车视觉 - 西安邮电大学 - AI小布丁
- Linux下找出吃内存的方法总结
- lightroom 闪退_UP加速器闪退怎么办 UP加速器闪退解决方法
- 南京:第三届软博会“外包”将唱主角
- centos7 搭建Docker Registry
- 米家小白增强固件_中考体育:男1000米/女800米想拿满分,掌握呼吸法是关键
- 在用ganglia时出现You don‘t have permission to access ganglia on this server
- C语言杂记-vector 、 stack and queue
- [记录]Python的master-worker和epoll模式
- python自动写工作日志_python自动化执行重复工作
- GridView的DataFormatString格式化字符串
- wps怎么利用c语言编辑,WPS如何转换成图片?三种方法帮你实现
- 欧拉定理(Tetration,玲珑杯 Round#5 E lonlife 1060)
- 同一服务器两个端口不同的应用session覆盖解决方案
- Android省市县三级联动 真实项目抽出 调用只需3行代码
- 【plang 1.4.6】Plang高级编程语言(发布)
- CorelDRAW x8警告您所用的软件疑似非法盗版软件,软件功能3天内将被永久停用,解决方法教程
- 服务器网站绕过备案,腾讯云服务器如何利用阿里DCDN绕过备案
- Keras实例教程(3)