函数递归

2023-11-02

1.递归是什么?

递归是指函数可以调用自身来解决问题的一种编程技巧。在C语言中,递归是通过函数调用自己来实现的。使用递归可以使某些问题更容易理解和处理。例如,计算一个数的阶乘可以使用递归来实现。
递归函数有两个要素:递归基(也称边界条件)和递归式。递归基是指当问题达到一定规模时,不再需要递归而可以直接返回结果。递归式表示问题可以通过一个较小规模的问题和少量的计算得到解决。在递归调用过程中,每个函数调用都有自己的一组参数和局部变量,因此可以处理不同的问题,但它们共享静态数据。
递归在实际编程中需要考虑递归深度和效率问题,因为过深的递归会导致栈溢出,而复杂的递归算法可能会导致性能问题。因此,在使用递归时需要权衡掌握好递归的优缺点,选择合适的算法实现。

2.递归的限制条件

在C语言中,递归的限制条件是递归深度和所需的堆栈空间。在递归调用函数时,每次调用都会在堆栈上创建一个新的栈帧,并将变量、返回地址等信息保存在该栈帧中,以便在函数返回时能够恢复上一个栈帧。如果递归深度过深或者所需的堆栈空间过大,堆栈会超出其分配的内存空间,从而导致程序崩溃。因此,在使用递归时,需要谨慎考虑递归深度以及所需的堆栈空间,并避免产生无限递归的情况。

3.递归举例

汉诺塔(Tower of Hanoi)是一种经典的递归问题,它的解法非常优美。现在我们来通过C语言的代码来理解汉诺塔问题。

汉诺塔问题是这样的:有三根柱子A、B、C,其中柱子A上有n个盘子,盘子从小到大依次放在柱子上,要将所有盘子移动到柱子C上,移动过程中可以借助柱子B,但要求小盘子必须在大盘子上面。具体的图示可以自行搜索。

现在我们来看看用C语言如何实现汉诺塔问题:

#include <stdio.h>

//将n个盘子从A柱子移动到C柱子
void hanoi(int n, char A, char B, char C) {
    if (n == 1) {  //递归结束条件
        printf("从%c移到%c\n", A, C);
    } else {
        hanoi(n-1, A, C, B);  //先将n-1个盘子从A柱子移动到B柱子
        printf("从%c移到%c\n", A, C);  //将A上最后一个盘子移动到C
        hanoi(n-1, B, A, C);  //最后将B上的n-1个盘子移动到C柱子上
    }
}

int main() {
    int n = 3;
    hanoi(n, 'A', 'B', 'C');
    return 0;
}

在上面的代码中,我们定义了一个名为hanoi的递归函数,函数的参数n表示要将n个盘子从A柱子移动到C柱子,A、B、C三个参数分别表示柱子A、B、C,函数中先判断递归结束的条件,如果只有1个盘子则直接将其从A移动到C,否则将n-1个盘子从A移动到B,再将A上最后1个盘子移动到C,最后将B上的n-1个盘子移动到C。

在main函数中,我们调用hanoi函数将3个盘子从A柱子移动到C柱子,输出结果如下:

从A移到C
从A移到B
从C移到B
从A移到C
从B移到A
从B移到C
从A移到C

可以看出,汉诺塔问题确实被优雅地解决了!

4.递归与迭代

递归和迭代都是求解问题的方法,但它们的实现方式不同。

递归是指函数调用自身,将原问题转化为规模更小的同类问题并解决,直到找到最简单的情况得以解决。C语言的递归函数需要满足两个条件:

  1. 基本出口(边界条件):这是递归算法最关键的一部分,必须明确定义一个或多个终止递归的判断条件,避免死循环。

  2. 递归调用:在函数的定义中,调用函数自身来解决规模更小的同类问题,直到达到基本出口。

例如,求一个数的阶乘,可以使用递归的方式:

unsigned int factorial(unsigned int n) {
    if (n == 0) {
        return 1; // 0的阶乘为1
    } else {
        return n * factorial(n-1); // 调用自身,规模减1
    }
}

迭代则是通过循环来重复执行一段代码,达到解决问题的目的。使用迭代算法来实现上述阶乘的例子:

unsigned int factorial(unsigned int n) {
    unsigned int result = 1;
    for (int i = 1; i <= n; ++i) {
        result *= i;
    }
    return result;
}

在实际应用中,递归和迭代各有优缺点。递归可以更直观地表达问题的本质,但在大规模问题上容易造成爆栈(stack overflow)等风险。迭代虽然实现起来相对简单且效率高,但往往需要更多的代码量和变量。需要根据不同的情况选择合适的算法。在这里插入代码片

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

函数递归 的相关文章

随机推荐

  • 蓝桥杯算法训练VIP-比赛安排

    题目 题目链接 题解 DFS 本题我们要开两个标记数组 flag数组是个二维数组 用于标记某两只队伍是否进行过比赛了 另一是一维数组vis 用于标记某只队伍是否比过赛 两个数组的作用范围不同 vis数组只在每一行中有效 每到下一行时 vis
  • freeimage例子资料整理

    关于freeimage的一些实例代码 对学习freeimage很有帮助 about freeimage http www pudn com downloads169 sourcecode graph texture mapping deta
  • Kettle中“排序记录”的使用

    排序记录 作用很简单 就是对字段进行排序 一般很都是配合 去除重复记录 和 记录集连接 使用的 这里就简单介绍下排序记录的使用 核心对象 gt 转换 gt 排序记录 将 排序记录 拖拽到转换页面 配置参数 选择排序字段 data2 然后选择
  • HTML特殊字符符号大全

    HTML常用特殊字符 只要你认识了 HTML 标记 你便会知道特殊字符的用处 HTML 原代码 显示结果 描述 lt lt 小于号或显示标记 gt gt 大于号或显示标记 amp 可用于显示其它特殊字符 quot 引号 reg 已注册 co
  • C++ day2

    https note youdao com s BGiSQ9uwhttps note youdao com s BGiSQ9uw 封装一个结构体 结构体中包含一个私有数组 用来存放学生的成绩 包含一个私有变量 用来记录学生个数 提供一个公有
  • 范式建模和维度建模区别

    范式建模是只一份文件 维度建模是只一类文件
  • POJ1338~~~~~~丑数(经典dp)

    include
  • Android实战经验之图像处理及特效处理的集锦(总结版)

    1 Android学习笔记进阶之在图片上涂鸦 能清屏 2 Android学习笔记之详细讲解画圆角图片 3 Android学习笔记进阶20之得到图片的缩略图 4 Android学习笔记进阶19之给图片加边框 5 Android学习笔记进阶18
  • mac下hive-1.2.2-src版本的编译

    文章目录 1 下载 1 下载 官网 https github com apache hive 2 导入IDEA 进行编译 mvn clean install Phadoop 2 dist DskinpTests Dhadoop 23 ver
  • 软件测试自学怎么学?

    很多朋友想要入行软件测试 但是都不知道该怎么学 抽个时间简单的给大家说下 对于0基础的朋友 应该怎么去学习软件测试 学习软件测试有2条路可以选 1 最省事的当然是找个靠谱的培训机构去培训啦 你就什么都不用想了 跟着培训结构认真的学习就行了
  • shell 如何判断某个文件名以某个字符开头

    问题 shell 如何判断某个文件名以某个字符开头 解决 var cn get the length of me 1 parameter 1 传要判断的文件名字 var 1 isCN false var 0 2 取var子串 从第0个字符起
  • unity2019中虚拟按钮的使用

    版本 unity2019 4 12f1 Visual Studio2019 1 window栏加入Vuforia Engine AR 此时可以正常使用AR相机了 2 利用vuforia码 建立一个空物体showcube 然后在空物体上加入V
  • Pywin32:Python库的简介、安装和使用攻略

    Pywin32 Python库的简介 安装和使用攻略 Pywin32是Python的一个强大而广泛使用的库 它提供了访问Windows API的接口 以实现处理Windows系统资源的功能 如窗口管理 注册表操作 消息传递等等 这里我们将为
  • 遗传算法解决TSP问题

    一 背景 遗传算法是基于自然选择和自然遗传机制的一种随机搜索算法 具有良好的并行性和全局寻优能力 能够自适应地调整搜索方向 这是一种相对来说比较简单的算法 因为它不需要问题求解者具备非常完备的问题领域知识 它能够通过类似生物体繁殖后代的机制
  • FreeRTOS学习笔记—任务创建和删除

    文章目录 一 任务创建和删除API函数 1 1 xTaskCreate 函数 1 2 xTaskCreateStatic 函数 1 3 vTaskDelete 函数 二 任务创建和删除 动态方法 2 1 任务要求 2 2 程序设计 2 2
  • 关于Collection下的removeAll方法抛出UnsupportedOperationException分析

    起因 这周在开发的过程遇到了以下这个错误 之前一直规范运用Collection的接口 所以这个异常比较少见 所以我就纳闷了 做个一个实验 package src import com google common collect Sets i
  • 《小家:越住越大2》

    第一章 餐厅如何避免杂乱 一般家庭的餐桌物品占用餐桌桌面面积普遍较高 显得餐桌杂乱 可以采用餐边柜与餐桌零距离接触方式方便杂物摆放 也可以采用移动是多层收纳车 如何避免孤单在厨房做饭 厨房与餐厅采用玻璃吊轨门连接 可以使用卡座代替普通餐椅
  • 12,verilog移位操作

    注 学习 交流就在博主的个人weixin公众号 FPGA动力联盟 留言或直接 博主weixin fpga start 私信 Verilog中的移位操作有两类 逻辑移位和算术移位 逻辑右移 gt gt 1个操作数向右移位 产生的空位用0填充
  • 毕业设计-基于深度学习的病理图像细胞核分割

    目录 前言 课题背景和意义 实现技术思路 一 相关技术介绍 二 基于双通路解码的病理图像细胞核分割 三 基于无锚检测的病理图像细胞核分割 实现效果图样例 最后 前言 大四是整个大学期间最忙碌的时光 一边要忙着备考或实习为毕业后面临的就业升学
  • 函数递归

    函数递归 1 递归是什么 2 递归的限制条件 3 递归举例 4 递归与迭代 1 递归是什么 递归是指函数可以调用自身来解决问题的一种编程技巧 在C语言中 递归是通过函数调用自己来实现的 使用递归可以使某些问题更容易理解和处理 例如 计算一个