C语言—函数递归

news2024/12/29 13:00:38

一、递归概念

递归其实是⼀种解决问题的⽅法,在C语⾔中,递归就是函数⾃⼰调⽤⾃⼰。下面举一个例子:

上述就是⼀个简单的递归程序,只不过上⾯的递归只是为了演⽰递归的基本形式,不是为了解决问题,代码最终也会陷⼊死递归,导致栈溢出(Stack overflow)。

递归的思想:把⼀个⼤型复杂问题层层转化为⼀个与原问题相似,但规模较⼩的⼦问题来求解;直到⼦问题不能再被拆分,递归就结束了。所以递归的思考⽅式就是把⼤事化⼩的过程。递归中的递就是递推的意思,归就是回归的意思。

二、递归的限制条件

递归在书写的时候,有2个必要条件:

• 递归存在限制条件,当满⾜这个限制条件的时候,递归便不再继续。

• 每次递归调⽤之后越来越接近这个限制条件。

三、递归举例

(3.1)求n的阶乘

计算n的阶乘(不考虑溢出),n的阶乘就是1~n的数字累积相乘。

(3.1.1)分析和代码实现

首先我们要知道n的阶乘的公式:n! = n ∗ (n − 1)! 

例如:

这样的思路就是把⼀个较⼤的问题,转换为⼀个与原问题相似,但规模较⼩的问题来求解的。通过上图继续分析:(假设求4的阶乘)

当n<=1时,n的阶乘是1,其余n的阶乘都是可以通过上述公式进行拆分计算。

因此,n的阶乘的递归公式如下:

那我们就可以写出函数Fact求n的阶乘,假设Fact(n)就是求n的阶乘,那么Fact(n-1)就是求n-1的阶乘,函数如下:

测试:

(3.1.2)画图推演

(3.2)顺序打印一个整数的每一位

输⼊⼀个整数m,按照顺序打印整数的每⼀位。例如:

(3.2.1)分析和代码实现

如果n是⼀位数,n的每⼀位就是n自己。
n是超过1位数的话,就得拆分每⼀位。例如:1234%10就能得到4,然后1234/10得到123,这就相当于去掉了4然后继续对123%10,就得到了3,再除10去掉3,以此类推。不断的 %10 和 \10 操作,直到1234的每⼀位都得到;但是这⾥有个问题就是得到的数字顺序是倒着的。我们发现⼀个数字的最低位是最容易得到的,通过%10就能得到,那我们假设写⼀个函数Print来打印n的每⼀位,如下表⽰:

直到被打印的数字变成⼀位数的时候,就不需要再拆分,递归结束。代码如下:

测试:

在这个解题的过程中,我们就是使⽤了⼤事化⼩的思路(以1234为例)把Print(1234)打印1234每⼀位,拆解为⾸先Print(123)打印123的每⼀位,再打印得到4,Print(123)打印123每⼀位,拆解为⾸先Print(12)打印12的每⼀位,再打印得到的3,直到Print打印的是⼀位数,直接打印就⾏。

(3.2.2)画图推演

以1234每⼀位的打印来推演⼀下。

四、递归和迭代

在C语⾔中每⼀次函数调⽤,都要需要为本次函数调⽤在栈区申请⼀块内存空间来保存函数调⽤期间的各种局部变量的值,这块空间被称为运⾏时堆栈,或者函数栈帧。函数不返回,函数对应的栈帧空间就⼀直占⽤,所以如果函数调⽤中存在递归调⽤的话,每⼀次递归函数调⽤都会开辟属于⾃⼰的栈帧空间,直到函数递归不再继续,开始回归,才逐层释放栈帧空间。所以如果采⽤函数递归的⽅式完成代码,递归层次太深,就会浪费太多的栈帧空间引起栈溢出(stack overflow)的问题。

所以如果不想使⽤递归就得想其他的办法,通常就是迭代的⽅式(通常就是循环的⽅式)。

⽐如:计算n的阶乘。

事实上,我们看到的许多问题是以递归的形式进⾏解释的,这只是因为它⽐⾮递归的形式更加清晰,但是这些问题的迭代实现往往⽐递归实现效率更⾼。
当⼀个问题⾮常复杂,难以使⽤迭代的⽅式实现时,此时递归实现的简洁性便可以补偿它所带来的运⾏时开销。

例如:求第n个斐波那契数

注:斐波那契数列第一项和第二项都是1,后面每一项等于前两项相加。

假设我们写了一个Fib函数求第n个斐波那契数列,那么根据斐波那契数列的性质可以得到以下公式:

看到这公式,我们很容易就能写出递归形式的代码:

测试:

当我们n输⼊为50的时候,需要很⻓时间才能算出结果,这个计算所花费的时间,是我们很难接受的,这也说明递归的写法是⾮常低效的,那是为什么呢?其实递归程序会不断的展开,在展开的过程中,我们很容易就能发现,在递归的过程中会有重复计算,⽽且递归层次越深,冗余计算就会越多。如图:

我们可以写代码统计一下第三个斐波那契数被计算的次数。

这⾥我们看到了,在计算第40个斐波那契数的时候,使⽤递归⽅式,第3个斐波那契数就被重复计算了39088169次,这些计算是⾮常冗余的。所以斐波那契数的计算,使⽤递归是⾮常不明智的,我们就得想迭代的⽅式解决。我们知道斐波那契数的前2个数都1,然后前2个数相加就是第3个数,那么我们从前往后,从⼩到⼤计算就⾏了。代码如下:

解释:我们可以把a看成是第一个斐波那契数,b看成是第二个斐波那契数,c是要求的第n个斐波那契数,因为前两个斐波那契数没有必要求,所以求第三个及之后的斐波那契数需要累加n-2次,所以循环条件是n>2且每次n--。令a = b,b = c,是为了每次进入循环时,a,b分别为第n个斐波那契数的前2项和前1项。

五、拓展问题

青蛙跳台阶

题目:一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。如图所示:

思路:由题可知,当n等于1时,只有一种跳法,当n等于2时,有两种跳法。假设我们写一个climbStairs函数用来求青蛙跳上一个n级台阶有多少种跳法,那么当n大于等于3时,第一次跳有两种情况,如果第一次跳了一步,那么后面的台阶就有climbStairs(n-1)种方法,如果第一次跳了两步,那么后面的台阶就有climbStairs(n-2)种方法。由此我们可以得到公式:

代码为:

测试:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2040902.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ddos造成服务器瘫痪后怎么办

在服务器遭受DDoS攻击后&#xff0c;应立即采取相应措施&#xff0c;包括加强服务器安全、使用CDN和DDoS防御服务来减轻攻击的影响。rak小编为您整理发布ddos造成服务器瘫痪后怎么办。 当DDoS攻击发生时&#xff0c;首先要做的是清理恶意流量。可以通过云服务提供商提供的防护措…

java解析facebook的android app直投下的Referral URL

背景&#xff1a; 在facebook的应用推广中&#xff0c;一般使用两种方式&#xff0c;一种是app直投&#xff0c;一种是w2a。 app直投就是用户点击广告直接跳转到应用商店进行下载应用 w2a就是通过落地页方式引导用户进行应用下载 在w2a模式下&#xff0c;可以通过落地页链接…

Repeat方法:取模运算教材与Unity控制台输出数值不同的原因

学习该知识点的参考教材&#xff1a;Unity API解析/陈宏泉编著.——北京&#xff1a;人民邮电出版社&#xff0c;2014.9 编辑脚本的环境&#xff1a;Visual Studio 2022 在学习该本教材的第五章Mathf类的内容&#xff0c;通过跟随教材上的代码了解不同UnityAPI的具体用法时&a…

【数据结构】七、查找:1.查找的概念、线性结构查找(顺序、折半(二分)、插值、稠密、分块、倒排)

一、查找Search 文章目录 一、查找Search1.查找的基本概念1.1基本概念1.2算法评价标准 二、线性结构1.顺序表查找❗1.1顺序查找1.1.1算法思想1.1.2顺序查找效率分析 2.有序表查找❗2.1折半查找2.1.1算法思想2.1.2判定树构造2.1.3通过判定树进行查找效率分析2.1.4被查找概率不相…

ReactNative笔记(自用)

环境 ios更换gem镜像源&#xff1a; 查看当前源: gem sources -l 移除默认源: gem sources --remove https://rubygems.org/。添加新的源: 添加 Ruby China 的镜像源&#xff1a; gem source -a https://gems.ruby-china.com/或者添加其他镜像源。 清华大学的gem源: htt…

进阶-1.存储引擎

存储引擎 存储引擎1.MySQL体系结构2.存储引擎简介3.存储引擎特点3.1 InnoDB3.2 MyISAM3.3 Memory 4. 存储引擎选择 存储引擎 1.MySQL体系结构 2.存储引擎简介 存储引擎就是存储数据、建立索引、更新/查询数据等技术的实现。存储引擎是基于表的&#xff0c;而不是基于库的&…

【数学分析笔记】第2章第1节实数系的连续性(1)

2. 数列极限 2.1 实数系的连续性 人类对数系认识的历史&#xff1a; 人类最早对数系的认识是自然数集合 N \mathbb{N} N&#xff0c;自然数系对加法和乘法是封闭的&#xff08;这里的封闭是指&#xff1a;若 m ∈ N , n ∈ N ⇒ m n ∈ N , m n ∈ N m\in\mathbb{N},n\in\ma…

芯片用什么胶粘接牢固?​​​​​​​

芯片用什么胶粘接牢固?芯片粘接胶的牢固性对于电子产品的性能和可靠性至关重要。选择合适的胶水可以确保芯片能够稳定、可靠地固定在基板上。芯片的粘接通常涉及几种不同类型的胶水&#xff0c;每种胶水都有其特定的应用场景和性能特点。以下是几种常见的用于芯片粘接的胶水类…

C Primer Plus第十二章编程练习

第十二章编程练习 第一题要求我们不使用全局变量&#xff0c;修改程序12.4&#xff0c;那我们就用指针作为参数去传递变量的地址&#xff0c;去修改变量的值&#xff0c;完整程序代码以及运行结果如下&#xff1a; #include<stdio.h> //int units 0; void critic(int …

node卸载与安装

1.直接使用卸载程序卸载 2.安装新的Node 官网下载并执行下一步直到完成 3.Idea配置不同版本的node file->settings->Languages & Frameworks->Node.js and NPM->增加带选项->选择指定版本

ubuntu下使用docker、socket、yolov5进行图像处理数据交互记录

ubuntu下使用docker、socket、yolov5进行图像处理数据交互记录 概述&#xff1a;主要实现了在宿主机上通过8000端口传递一张图像给docker镜像&#xff0c;然后镜像中处理后&#xff0c;通过8001端口回传处理后的图像给宿主机。 第一章、构建镜像 一、dockerfile文件 1.拉取…

jQuery:配置与选择器

一&#xff0c;jQuery的配置 jQuery下载 这里以compressed为例&#xff0c;根据喜好也可以选择uncompressed版本。 进入jQuery代码中&#xff0c;右键另存为&#xff0c;保存到自己项目中&#xff1a; 导入jQuery <!DOCTYPE html> <html lang"en"><…

WO Mic 手机变身免费麦克风

目录 一、主要特点 1.支持多种连接方式 2.应用广泛 3.低延迟 4.简易配置 5.自动连接 6.音频格式 二、软件下载 三、软件安装 四、系统连接 五、测试 直播的时候,上课的时候,会议的时候……突然发现没有麦克风或者电脑麦克风有故障,这可怎么办呢?今天给大家介绍一…

ONNX深入研究(1):AI模型优化与加速方法

得益于现有的硬件和加速器&#xff0c;深度学习在 2010 年代初开始兴起&#xff0c;在这种支持下&#xff0c;研究人员和工程师提出了更复杂、更大的模型。然而&#xff0c;内存消耗和执行时间等限制仍然是一个挑战。由于计算资源的限制&#xff0c;这些挑战在工程和商业领域变…

UE5学习笔记11-为拿取武器添加动画

一、一点说明 动画实例通过扩展为所有机器上的每个字符都存在动画蓝图&#xff0c;动画实例只能访问该计算机上的变量。 二、思路 我在武器组件中有一个武器类的指针&#xff0c;判断当前指针是否为空去判断当前角色是否装备武器 三、实现 1.在角色C类中添加是否装备武器的函…

OpenCV--图片操作

一.图片旋转 图片旋转是图像处理中的一种基本操作&#xff0c;用于将图像按照指定的角度进行旋转。旋转操作在图像编辑、计算机视觉和图形学等领域中非常常见&#xff0c;通常用来调整图像的方向或在图像识别中进行数据增强。 旋转的基本原理 图片旋转涉及到将每个像素从原始…

(贪心) LeetCode 376. 摆动序列

原题链接 一. 题目描述 如果连续数字之间的差严格地在正数和负数之间交替&#xff0c;则数字序列称为 摆动序列 。第一个差&#xff08;如果存在的话&#xff09;可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。 例如&#xff0c; [1, 7, 4, 9, 2,…

电脑技巧:电脑系统盘文件清理指南

目录 一、可以安全删除的文件 1.1. 临时文件 1.2. 系统缓存文件 1.3. 回收站 1.4. 安装包缓存 1.5. 系统还原点 1.6. 已下载的更新文件 1.7. 浏览器缓存 1.8. Thumbs.db 文件 1.9. Windows日志文件 1.10. Windows.old 文件夹 二、系统文件清理注意点 三、系统文件…

推荐一款Python开源移动应用安全测试分析工具!!!

今天给大家推荐一个安全测试相关的开源项目&#xff1a;nccgroup/house 1、介绍 它是一个由 NCC Group 开发的&#xff0c;一个基于Frida和Python编写的动态运行时移动应用分析工具包&#xff0c;提供了基于 Frida 的 Web GUI 界面&#xff0c;旨在简化动态函数挂钩的过程&am…

Linux---04---Vim编辑器

一、vi/vim编辑器介绍 vi 是 visual interface 的简称&#xff0c;是Linux系统提供的一个文本编辑工具&#xff0c;可以对文件内容进行编辑&#xff0c;类似于Windows中的记事本。 vim 是 vi 的加强版本&#xff0c;兼容 vi 的所有指令&#xff0c;不仅能编辑文本&#xff0c…