一、什么是递归函数

函数调用自己的行为就是递归,递归必须要有终止条件,不然它会无限递归。

1.先看一下一个递归的例子

此程序的factorial函数参数从大到小地一级一级地调用自己,直到参数为1,然后函数就开始返回一级一级的从小到大地累乘,然后就计算出number的阶乘了。

#include<stdio.h>
#include<stdlib.h>
int factorial(int num);
int main(void)
{
int number=0;
int result=0;
printf("Calculating factorial: ");
scanf("%d",&number);
result=factorial(number);
printf("The result is %d\n",result);
system("pause");
return 0;
} int factorial(int num)
{
if(num == 1)
return 1;
else
return num*factorial(num-1);
}

2.递归的基本原理

以下是《C Prinmer Plus》对于递归的描述:

  1. 每级调用都有自己的变量
  2. 每次函数调用都会返回一次
  3. 递归函数中位于递归调用之前的语句,均按被调函数的顺序执行。
  4. 递归函数中位于递归调用之后的语句,均按被调函数相反的顺序执行。
  5. 虽然每级递归都有自己的变量,但是并没有拷贝函数的代码。
  6. 递归函数必须包含能让递归调用停止的语句。

    我个人认为递归就是把你要干的事情抽象一个成可以有限步数解决的函数,然后某一步解决不了就再调用这个函数,直到可以解决(结束递归的条件)这个问题就返回。
    下面再看一个具体的例子来了解递归。

二、汉诺塔问题

1.简要概括一下汉诺塔的故事

汉诺塔由法国数学家爱德华·卢卡斯创造,他曾经编写了一个印度的古老传说:

在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔。不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片:一次只移动一片,不管在哪根针上,小片必须在大片上面。僧侣们预言,当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭,而梵塔、庙宇和众生也都将同归于尽。

2.回到编程,汉诺塔问题主要就是解决这个问题:

有A、B、C三根针,A上从小到大放着n层盘子,要从A上所有的盘子移动到C盘上。
条件是一次只能移动一个盘子,无论什么时候小盘子必须在大盘子上面
汉诺塔问题求的是把盘子从A移到C总共的移动次数是多少。

这是我之前追踪四层汉诺塔运行步骤画的笔记




事实证明,没多大帮助。
要想理解递归必须要放弃理解递归,放弃跟踪全程步骤。
解决问题是计算机的事,你只要明确要把每一步怎么传给计算机,递归两层之间怎么交接,以及递归结束的条件就可以。

3.怎么解决汉诺塔问题

要解决汉诺塔问题就要用到递归思想,这里拿四层汉诺塔举例子:

要完成四层汉诺塔,需要先把第四层盘子从A柱放到C柱,而要把第四层盘子放到C柱,就要把上面三层的盘子放到B柱:

那么要把这三层盘子移到B柱,那么就要先把第三层盘子移到B柱。
要把第三层盘子移到B柱,就要把第二层盘子移到C柱子。
要把第二层盘子移到C柱,就要把第一层盘子移到B柱子。
移动一层汉诺塔到另一个柱不简单吗?
这样子把问题解决了,第四层盘子就可以移动到C柱上了。
然后把剩下的三层汉诺塔也按照上面的思想,就可以移动到C柱上了。

4.具体代码实现

把大象装进冰箱需要多少步

  1. 把冰箱门打开
  2. 把大象放进去
  3. 把冰箱门关上

把汉诺塔放到C柱需要多少步

  1. 把底层上面的盘子放到B柱
  2. 把最底层盘子放到C柱
  3. 把B柱那些盘子放到C柱

抽象一下就是:

  1. 把n-1层盘子从起点移到暂存区
  2. 然后把第n层盘子从起点移到终点
  3. 然后把n-1层盘子从暂存区移到终点
在这里可以创建一个move函数来移动盘子
void move(int pile, char src, char tmp, char dst);

src就是源起点,tmp就是暂存区,dst就是终点

最外层的move函数完成的是把pile层汉诺塔从src经过tmp移动到dst

现在要把大象装进冰箱了

在move函数里面调用move函数来解决之后的问题:

1. 把冰箱门打开
move(pile - 1, src, dst, tmp);

这层move完成的是把pile-1层汉诺塔从src经过dst移动到tmp


2.把大象塞进去
move(1, src, tmp, dst);

这层move完成的是把最底层汉诺塔盘子从src直接移动到dst


3.把门关上
move(pile - 1, tmp, src, dst);

这层move完成的是把pile-1层汉诺塔从tmp经过src移动到dst

每一层move函数都有他自己的起点、暂存区和终点,我们只需要把上一层的起点、暂存区和终点传过去就行了。

5. 完整代码

以下是完整代码:

#include<stdio.h>
#include<stdlib.h>
#define MAX_LEVEL 30 //设置最大层数 int steps = 0;//steps保存盘子移动次数
void move(int pile, char src, char tmp, char dst); int main(void)
{
int levels = 0;
printf("输入汉诺塔层数(1~%d):", MAX_LEVEL);
scanf("%d", &levels);
if (levels > 0 && levels < 30)//判断是否符合层数范围
{
move(levels, 'A', 'B', 'C');
printf("共移动了%d次。\n", steps);
system("pause");
return 0;
}
printf("输入范围错误\n");
system("pause");
return 1; } void move(int pile, char src, char tmp, char dst)
{
if (pile == 1)//pile=1问题就好解决了
{
printf("%c --> %c\n", src, dst);
steps++;
return;
}
move(pile - 1, src, dst, tmp);
move(1, src, tmp, dst);
move(pile - 1, tmp, src, dst);
}

运行结果如下:

C语言汉诺塔递归算法实现的更多相关文章

  1. C语言之算法初步(汉诺塔--递归算法)

    个人觉得汉诺塔这个递归算法比电子老鼠的难了一些,不过一旦理解了也还是可以的,其实网上也有很多代码,可以直接参考.记得大一开始时就做过汉诺塔的习题,但是那时代码写得很长很长,也是不理解递归的结果.现在想 ...

  2. python的递归算法学习(3):汉诺塔递归算法

    汉诺塔问题是递归函数的经典应用,它来自一个古老传说:在世界刚被创建的时候有一座钻石宝塔A,其上有64个金蝶.所有碟子按从大到小的次序从塔底堆放至塔顶.紧挨着这座塔有另外两个钻石宝塔B和C.从世界创始之 ...

  3. C语言 汉诺塔问题

    //凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 汉诺塔是由三根杆子A,B,C组成的.A杆上有n个(n>1)穿孔圆盘,盘的尺寸由下到上依次变小.要求按 ...

  4. 题目1458:汉诺塔III(不一样的汉诺塔递归算法)

    题目链接:http://ac.jobdu.com/problem.php?pid=1458 详解链接:https://github.com/zpfbuaa/JobduInCPlusPlus 参考代码: ...

  5. c语言-汉诺塔递归调用

    #include<stdio.h> int main() { void hano_tower(int n,char one,char two,char three); int m=0; p ...

  6. C语言数据结构----递归的应用(斐波拉契数列、汉诺塔、strlen的递归算法)

    本节主要说了递归的设计和算法实现,以及递归的基本例程斐波拉契数列.strlen的递归解法.汉诺塔和全排列递归算法. 一.递归的设计和实现 1.递归从实质上是一种数学的解决问题的思维,是一种分而治之的思 ...

  7. 汉诺塔(河内塔)算法 ----C语言递归实现

    汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具.大梵天创造世界的时候做了三根金刚石柱子, 在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘.大梵天命令婆罗门把圆盘从下面开始按大小顺 ...

  8. 【C语言】汉诺塔问题

    之前遇见这个问题,非常费劲地理解了,并写出代码,然后过段时间,再遇见这个问题,又卡住了,如此反反复复两三次,才发现自己对递归的理解依然很肤浅.今天无聊,重温<算法:c语言实现>一书,又遇见 ...

  9. 运用Turtle实现汉诺塔的可视化运行(递归算法)

    运用Turtle实现汉诺塔的可视化运行(递归算法) 汉诺塔问题又名河内塔问题,是源于印度一个古老传说的益智玩具.大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆 ...

  10. 汉诺塔问题(The Tower of Hanoi)的递归算法与非递归算法

    非递归算法: 根据圆盘的数量确定柱子的排放顺序: 若n为偶数,按顺时针方向依次摆放 A B C: 若n为奇数,按顺时针方向依次摆放 A C B. 然后进行如下操作: (1)按顺时针方向把圆盘1从现在的 ...

随机推荐

  1. Modbus转Profinet网关改写变频器运行状态在1200PLC程序控制实例

    兴达易控Modbus转Profinet网关将丹佛斯变频器接入西门子 1200PLC 配置案例 案例简介: 本案例是兴达易控Modbus转Profinet网关连接丹佛斯变频器在西门子 1200PLC程序 ...

  2. mysql8安装踩坑记

    背景:已安装mysql5.7版本 问题一:默认的3306端口被占用 进入mysql5.7的my.ini文件,更改port为3307或者其他未被占用的端口 问题二:Install/Remove of t ...

  3. DevOps平台建设的关键点是什么?

    关键还是在人 找到一个「吃过猪肉,见过猪跑的」,你问他什么是猪,他自然比「没吃过猪肉,没见过猪跑的人」更了解猪.海豚海豚,你知道猪是什么样么?它都没上过陆地,这辈子都没见过猪,它哪知道猪是什么样. 有 ...

  4. android 尺寸适配相关

    Android上常见度量单位 px(像素):屏幕上的点,绝对长度,与硬件相关. in(英寸):长度单位. mm(毫米):长度单位. pt(磅):1/72英寸,point. dp(与密度无关的像素):一 ...

  5. 文心一言 VS 讯飞星火 VS chatgpt (108)-- 算法导论10.1 6题

    六.用go语言,说明如何用两个栈实现一个队列,并分析相关队列操作的运行时间. 文心一言: 使用两个栈实现队列的基本思想是利用一个栈(stack1)来处理入队操作,另一个栈(stack2)来处理出队操作 ...

  6. CF1401C

    题目简化和分析: 交换数组使其变为升序,满足交互的两数 \(a_i\) 与 \(a_j\),$ \min{a_i(1\le i\le n)}|\gcd(a_i,a_j)$ . 简单思维题,Div.2 ...

  7. 聊聊RNN与seq2seq

    seq2seq模型也称为Encoder-Decoder模型.顾名思义,这个模型有两个模块--Encoder(编码器)和Decoder(解码器).编码器对输入数据进行编码,解码器对被编码的数据进行解码. ...

  8. redis 怎么样查看key的大小,多大的key才算大key?

    查看key大小的命令 # 格式memory usage [key-name]# 例如:我要查 yino_hash_key 这个key的大小,就在命令行中输入 memory usage yino_has ...

  9. 从windows到linux,图形化操作到命令行操作讲解

    作为一个后端开发人员,刚开始进入到职场中,linux还不是必备项.但是随着开发经验的提升,慢慢就会接触到linux,所以就有了那句:开发必须要会linux.一开始我也不知道linux是干嘛的,学那些命 ...

  10. 25. 干货系列从零用Rust编写正反向代理,序列化之serde是如何工作的

    wmproxy wmproxy已用Rust实现http/https代理, socks5代理, 反向代理, 静态文件服务器,四层TCP/UDP转发,内网穿透,后续将实现websocket代理等,会将实现 ...