一、什么是递归函数

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

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. Goobye, cnblogs

    转 typecho 了,个人网站的客制化程度当然不是 cnblogs 能比得上的. <cirnovsky.cf>

  2. Codechef - Longest AND Subarray(位运算)

    题目大意   给定一个正整数N,其序列为[1, 2, 3, ..., N],找到一个长度最大的连续子列,使得其所有元素取与运算的结果为正(最终输出只需要输出最大长度即可). 思路   刚开始可能并不好 ...

  3. C++ 对拍详解 和解读

    对拍是什么# ​对拍,是一个比较实用的工具.它能够非常方便地对于两个程序的输出文件进行比较,可以帮助我们实现一些自动化的比较输出结果的问题. ​众所周知,几乎每一道编程题目,都会有某种正解能拿到满分: ...

  4. Python join拼接

    import os print(os.path.join("I","love","you.")) # /XXX 代表的是绝对路径 这个变量之 ...

  5. [SWPUCTF 2021 新生赛]sql

    看到网站上写着参数是wllm,就用wllm=1试了一下,发现是SQL注入 查找字段数时,提示请勿非法操作 说明空格出现过滤,可以用/**/绕过 http://1.14.71.254:28347/?wl ...

  6. client-go实战之七:准备一个工程管理后续实战的代码

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是<client-go实战> ...

  7. 动态规划 DP 的一些笔记以及解题思路

    万物的开始,首先介绍一下动态规划(dynamic programming,DP)的基本概念:动态规划适用于有重叠子问题和最优子结构性质的问题,并且记录所有子问题的结果,因此动态规划方法耗费时间远远少于 ...

  8. Android dumpsys介绍

    目录 一.需求 二.环境 三.相关概念 3.1 dumpsys 3.2 Binder 3.3 管道 四.dumpsys指令的使用 4.1 dumpsys使用 4.2 dumpsys指令语法 五.详细设 ...

  9. [ABC276Ex] Construct a Matrix

    没有题解,所以来写一篇. Description 构造一个 \(N\times N\) 的矩阵 \(A\),其中 \(A_{i,j}\in {0,1,2}\),要求同时满足 \(Q\) 条限制. 每条 ...

  10. Chromium Trace and Perfetto使用详解

    1. Trace chromium 在 base 库中提供了 base::trace_event::TraceLog 类,该类是 TRACE_EVENT* , TRACE_COUNTER* 等宏的底层 ...