一、什么是递归函数

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

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. 「ABC 218」解集

    E 倒流一下,然后把负权边置零后跑 MST 即可. #include<cstdio> #include<vector> #include<algorithm> us ...

  2. Solution Set -「ARC 124」

    「ARC 124A」LR Constraints Link. 我们可以把 \(1\sim n\) 个盒子里能放的球的编号集合全部求出来.然后就直接来. 注意题目已经给出了 \(k\) 个球的位置,所以 ...

  3. 用go封装一下二级认证功能

    用go封装一下二级认证 本篇为用go设计开发一个自己的轻量级登录库/框架吧 - 秋玻 - 博客园 (cnblogs.com)的二级认证业务篇,会讲讲二级认证业务的实现,给库/框架增加新的功能. 源码: ...

  4. 前端三件套系例之CSS——CSS3基础样式

    文章目录 1.宽和高 案例 2.字体属性 2-1 文字字体 2-2 字体大小 2-3 字重(粗细) 2-4 文本颜色 2-5 总结 2-6 案例 文字属性 3-1 文字对齐 3-2 文字装饰 3-3 ...

  5. MySQL系列之——SQL介绍、常用SQL分类、数据类型、表属性、字符集、DDL应用、DCL应用、DML应用(增删改)、DQL应用(select )、元数据信息、show命令

    文章目录 一 SQL介绍 二 常用SQL分类 2.1 客户端命令 三 数据类型.表属性.字符集 3.1 数据类型 3.1.1 作用 3.1.2 种类 3.2 表属性 3.2.1 列属性 3.2.2 表 ...

  6. Go 复合类型之字典类型介绍

    Go 复合类型之字典类型介绍 目录 Go 复合类型之字典类型介绍 一.map类型介绍 1.1 什么是 map 类型? 1.2 map 类型特性 二.map 变量的声明和初始化 2.1 方法一:使用 m ...

  7. CF1333A [Little Artem]

    Problem 题目简述 给你一个 \(n \times m\) 的方格,构造一个方案,使得方案中 \(B = W + 1\). \(B\):相邻的格子有至少一个白色格子的黑色格子的个数. \(W\) ...

  8. CF48C [The Race]

    Problem 题目简述 现有 \(n\) 个已经加过油的加油站,如果当前剩余油量 \(< 10\) 升,则会加 \(x\) 升的油. 初始状态下,有 \(x\) 升油.每个加油站之间的距离为 ...

  9. SNN_SRM模型

    # SRM模型 ## 早期SRM模型 Spike Response Modul(SRM)模型将传统的LIF微分模型换成了一个关于输入.输出的脉冲函数,可以将脉冲神经网络简化为第二代神经网络. 基本公式 ...

  10. [USACO2022OPEN S] Subset Equality S

    [USACO22OPEN] 题目描述 奶牛们正在尝试一种相互交换编码信息的新方法,她们在相关的字母中混入不相关的字母,使信息难以解码. 奶牛们传输两个字符串 \(s\) 和 \(t\),每个字符串的长 ...