C语言---函数的递归与迭代

递归的理解与限制条件

        所谓函数递归就是递推加回归的过程,就是函数自己调用自己。递归的思想就是把复杂的问题拆分成与原来那个大问题相似的子问题来求解,大事化小,像剥洋葱一样,最终把问题解决。

        递归的限制条件:

        一个递归程序,除了处理问题的递归主体之外,肯定是有递归的出口的(也就是递归的限制条件),每一次递归都是在栈区上给函数开辟一块空间,没有出口也就意味着栈没有销毁,最终会导致栈溢出的问题。所以每一次递归都要更加的接近这个限制条件才行。

递归举例

        问题1:求n的阶乘。

        问题分析:首先要知道什么是阶乘,就比如 5!= 5 * 4 * 3 * 2 * 1 ,就是一个数从自己本身,一直累乘到1。那么这个就可以用递归来解决,假设我们就求5的阶乘。

5! = 5 * 4 * 3 * 2 * 1

可以看成 5! = 5 * 4!

而4! = 4 * 3!

...................

从上边的分析就可以得出一个递归的公式

n! = n * (n - 1)! (由这个公式,我们就可以设计出一个计算 n! 的函数)

又因为 0! = 1,所以可以把这个设置成递归的出口。

        代码实现:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>//Fact函数用于计算n的阶乘
int Fact(int n)
{if (n == 0)return 1;elsereturn n * Fact(n - 1);
}int main()
{int number = 0;scanf("%d", &number);int res = Fact(number);printf("%d\n", res);return 0;
}

        画图理解:

 


        问题2:顺序打印一个整数的每一位。

        问题分析:假设现在有一个数字为1234,我想要顺序打印它的每一位,就是依次打印 1 2 3 4。我们如果想要直接获取到1,然后打印,这是非常困难的,但是,获取到最后一位的4很容易,只需要 1234 % 10 就可以了,又由于我现在想要顺序打印,所以4是要最后打印的,那就可以先打印前边的123,再打印4,而打印123,又可以拆分为先打印12,再打印3.............就是一个递归

假设Print是我们自己设计的一个函数,专门用来顺序打印数字的

那么上边的思路就转化如下:

--> Print(1234) --> Print(123) + 4;

--> Print(123) --> Print(12) + 3; 

--> Print(12) --> Print(1) + 2;

--> Print(1) --> 1(直接打印)

并且123,12......都是由原来的数字 num / 10 得到的

而由上边的分析就可以知道递归的出口就是当打印的数字为一位数的时候,就直接打印。

如果打印的数字是两位数,就先打印前边的数字,再打印最后一位的数字。

        代码实现:

#include<stdio.h>
void Print(int n)
{if (n > 9)//大于9就说明是超过一位的,需要递归处理{Print(n / 10);printf("%d ", n % 10);//获取n的最后一位,并且是最后打印}elseprintf("%d ", n);//如果只有一位,直接打印
}int main()
{int num = 0;scanf("%d", &num);Print(num);return 0;
}

        画图理解:

        再注意一个点,就是这里的Print函数是没有返回值的其实,但是得先Print函数调用结束之后才会执行下边的代码,这也叫回归。


        问题3:求第n个斐波那契数

        问题分析:所谓斐波那契数就是 1 1 2 3 5 8 13 21 34............其实这里的规律很容易被发现,就是从第三个数字开始,后一个数字是由前两个数字加起来。而第一个和第二个斐波那契数,我们就可以把它看做是函数的递归出口。

        代码实现:

#include<stdio.h>
//Fib(n)就表示的是第n个斐波那契数
int Fib(int n)
{if (n == 1 || n == 2)return 1;elsereturn Fib(n - 1) + Fib(n - 2);
}int main()
{int num = 0;scanf("%d", &num);printf("%d\n", Fib(num));return 0;
}

        附加:

        还有两个问题之前已经写过了,是青蛙跳台阶和汉诺塔问题。链接如下。

        用C语言函数递归实现青蛙跳台阶和汉诺塔问题-CSDN博客


递归与迭代

        在上边就提到过函数递归如果从来没有递归出口的话就会导致栈溢出的问题,同样的,就算有递归出口,如果递归的层次太深,也会导致栈溢出。

        如果不用递归的方式,迭代也是很好的解决方式,迭代通常就是由循环来实现的。它们俩是相辅相成的,不过迭代相对来说消耗的栈空间较少。效率要高一点。

迭代举例

        问题1:用迭代的方式实现n的阶乘。

        问题分析:刚才已经说了,迭代其实就是用循环来实现的,求n的阶乘可以先循环产生1~n之间的每一个数字,然后再累乘起来。

        代码实现:

#include<stdio.h>
int main()
{int res = 1;//res用来存最后的结果,初始化为1是因为便于下边直接累乘int num = 0;scanf("%d", &num);//for循环产生1~num的数字for (int i = 1; i <= num; i++){res *= i;}printf("%d\n", res);return 0;
}

        问题2:用迭代的方式求第n个斐波那契数

        问题分析:关于斐波那契数的定义已经在上边的递归里边讲到了。但是如果用递归求第50个斐波那契数的话,我们就会明显的发现,递归的结果迟迟没有出现,这就是上边提到的递归的层次太深了,会影响效率。

用迭代的方式:

为了计算第n个斐波那契数,我们可以先定义三个变量。

int a = 1;

int b = 1;

int c = 1;//这是第三个数字,用来最后返回的结果

根据斐波那契数列的规律,c可以通过a + b来实现,然后再把a的值改为b原来的值,b的值改为c的值,而现在的c就又可以由a+b来计算了,以此迭代下去,效果如下。

下边红色代表斐波那契数,而黑色就代表该数是第几个斐波那契数。

1 1 2 3 5 8 13 21.......

1 2 3 4 5 6  7  8.........

a b c..........................

   a b c.......................

最后解释一下为什么c为1,因为如果要求的是第1或者第2个斐波那契数,就不会进入循环,所以直接初始化为1,具体大家可以看下边的代码。

        代码实现:

#include<stdio.h>
int Fib(int n)
{int a = 1;int b = 1;int c = 1;//计算第三个斐波那契数及之后的数才进入循环//另外,找规律可以发现// 计算第3个斐波那契数只要计算一次// 计算第4个斐波那契数要计算两次.............while(n>=3){c = a + b;a = b;b = c;n--;}return c;
}int main()
{int num = 0;scanf("%d", &num);printf("%d\n", Fib(num));return 0;
}

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

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

相关文章

freqtrade在docker运行一个dryrun实例

检查配置 freqtrade trade --config user_data/config.json --strategy MlStrategy config文件,这个配置做期货为主&#xff0c;静态配置了交易对&#xff0c;同时端口和第一个bot要不一样&#xff0c;不然没有办法进行监控&#xff0c;甚至要冲突了。10S钟进行循环&#xff0c…

单片机学习笔记.PWM

PWM原理&#xff1a; 频率占空比&#xff1a;精度占空比变化步距 电机驱动电路&#xff1a;利用PWM实现呼吸灯代码 sbit LEDP2^0;//引脚定义unsigned char Time,i;//变量定义void Delay(unsigned int t)//定义延时 {while(t--); }main函数里&#xff1a;int main() {unsigned c…

【Git】解决使用SSH连接远程仓库时需要多次输入密码的问题

问题产生的原因&#xff1a;你的SSH私钥设置了密码短语&#xff08;passphrase&#xff09;。解决问题的方法&#xff1a;使用SSH代理&#xff08;ssh-agent&#xff09;&#xff0c;ssh-agent是一个后台运行程序&#xff0c;它会记住你解锁过的SSH私钥的密码短语&#xff0c;这…

机器学习—逻辑回归

一介绍逻辑回归是处理二分类问题的线性模型&#xff0c;通过sigmoid函数将线性输出映射到[0,1]&#xff0c;输出事件发生概率&#xff0c;广泛用于预测与分类。如果做坐标的话&#xff0c;特征就是p1和p2&#xff0c;结果就是y红的与绿的 二Sigma函数代码说明Sigmoid 函数定义&…

深入解读OpenTelemetry分布式链路追踪:原理与实践指南

深入解读OpenTelemetry分布式链路追踪&#xff1a;原理与实践指南 分布式系统在微服务架构下&#xff0c;服务调用链越来越复杂&#xff0c;追踪单次请求在各个微服务之间的执行情况成为运维与性能优化的关键。作为新一代开源标准&#xff0c;OpenTelemetry为分布式追踪、指标与…

【0基础PS】PS工具详解--图案图章工具

目录前言一、图案图章工具基础认知​二、工具选项栏参数详解​三、图案图章工具应用案例​总结前言 在 Adobe Photoshop 这一强大的图像处理软件中&#xff0c;图案图章工具是一个独具特色的功能&#xff0c;它允许用户利用预先定义好的图案进行绘画操作。 一、图案图章工具基…

剧本杀小程序系统开发:构建数字化剧本杀生态圈

在快节奏的现代生活中&#xff0c;人们越来越渴望在闲暇之余找到一种既能放松心情又能增进社交的方式。剧本杀&#xff0c;作为一种集推理、表演、社交于一体的新兴娱乐形式&#xff0c;恰好满足了这一需求。然而&#xff0c;随着市场的不断扩大&#xff0c;如何保持剧本杀的新…

【DL学习笔记】计算图与自动求导

计算图计算图&#xff08;Computation Graph&#xff09;是一种用于描述计算过程的图形化表示方法。在深度学习中&#xff0c;计算图通常用于描述 网络结构、运算过程 和数据流向。计算图是一种有向无环图&#xff0c;用图形方式来表示算子与变量之间的关系&#xff0c;直观高效…

大型地面光伏电站开发建设流程

​地面电站特特点&#xff1a;规模大&#xff0c;通常占用土地、水面等&#xff0c;地面式选址选项多&#xff0c;且不断拓展出新的用地模式&#xff0c;地面式选址集中在山体、滩涂、沼泽、戈壁、沙漠、受污染土地等闲置或废弃土地上。

除数博弈(动态规划)

爱丽丝和鲍勃一起玩游戏&#xff0c;他们轮流行动。爱丽丝先手开局。最初&#xff0c;黑板上有一个数字 n 。在每个玩家的回合&#xff0c;玩家需要执行以下操作&#xff1a;选出任一 x&#xff0c;满足 0 < x < n 且 n % x 0 。用 n - x 替换黑板上的数字 n 。如果玩家…

一起学springAI系列一:初体验

Spring AI是干嘛的官网最权威&#xff0c;直接粘贴&#xff1a;“Spring AI”项目旨在简化那些包含人工智能功能的应用程序的开发过程&#xff0c;同时避免不必要的复杂性。AI相关领域的功能对python的支持是最好的&#xff0c;相关供应商在出了啥功能的时候&#xff0c;都会优…

Ext JS极速项目之 Coworkee

ExtJS Coworkee 是什么? Ext JS 的 Coworkee 是一个由 Sencha 官方提供的完整员工管理应用示例,旨在展示 Ext JS 框架在企业级应用开发中的能力。 在线试用的地址是: https://examples.sencha.com/coworkee/#home 页面效果与布局 登录页面: 主页效果 左右分区结构:左…

飞算科技:原创技术重塑 Java 开发,引领行业数智化新浪潮

在科技革新的浪潮中&#xff0c;飞算科技作为一家坚持自主创新的数字科技企业&#xff0c;同时也是国家级高新技术企业&#xff0c;正深耕互联网科技、大数据、人工智能等前沿领域&#xff0c;为众多企业的数字化与智能化转型提供强劲动力。​飞算科技的成长轨迹&#xff0c;是…

cesium FBO(一)渲染到纹理(RTT)

一听到三维的RTT&#xff08;Render To Texture&#xff09;&#xff0c;似乎很神秘&#xff0c;但从底层实现一看&#xff0c;其实也就那样&#xff0c;设计API的哪些顶级家伙已经帮你安排的明明白白了&#xff0c;咱们只需要学会怎么用就可以了。我认为得从WebGL入手&#xf…

PNP机器人机器人学术年会展示灵巧手动作捕捉方案。

2025年8月1-3日&#xff0c;第六届中国机器人学术年会&#xff08;CCRS2025&#xff09;在长沙国际会议中心举行&#xff0c;主题“人机共融&#xff0c;智向未来”。PNP机器人与灵巧智能联合展出最新灵巧手模仿学习方案&#xff1a;基于少量示教数据即可快速复现复杂抓取动作&…

【45】C#入门到精通——C#调用C/C++生成动态库.dll及C++ 生成动态库.dll ,DllImport()方式导入 C++动态库.dll方法总结

文章目录1 C 生成动态库.dll2 C#调用C/C生成动态库.dll2.1 [DllImport()] 方式导入 C动态库.dll2.2 调用测试3 C/C 生成通用dll,改进3.1改进后.h3.2 .cpp3.2 C# 调用4 [DllImport()] 方式导入C生成的 .dll 总结4.1 指定路径导入4.2 .dll放在 执行目录下&#xff08;一定要放对&…

从协议栈到ath12k_mac_op_tx的完整调用路径

文章目录 从协议栈到ath12k_mac_op_tx的完整调用路径 1. 整体架构概览 2. 详细调用路径分析 2.1 应用层到Socket层 2.2 协议层处理 2.3 网络设备层到mac80211 2.4 mac80211发送入口 2.5 mac80211核心发送处理 2.6 mac80211发送核心处理 2.7 mac80211发送调度 2.8 最终驱动调用 …

WPFC#超市管理系统(4)入库管理

入库管理7. 商品入库管理7.2 入库实现显示名称、图片、单位7.3 界面设计7.3 功能实现7. 商品入库管理 数据库中StockRecord表需要增加商品出入库Type类型为nvarchar(50)。C#中的数据库重新同步StockRecord表在Entity→Model中新建枚举类型StockType namespace 超市管理系统.E…

CSS 打字特效

效果图.wxml <view class"tips"><text>{{ tipsText }}</text><text class"tips-line">|</text> </view>.wxss .tips{padding: 50rpx 100rpx;font-size: 28rpx; } .tips-line{color: #ccc;animation: tips-line .5s al…

直播小程序 app 系统架构分析

一、引言 直播行业近年来发展迅猛&#xff0c;直播小程序和 APP 成为众多用户获取直播内容以及主播进行内容输出的重要平台。一个完善且高效的系统架构是支撑直播业务稳定运行、提供优质用户体验的关键。本文将详细剖析直播小程序 / APP 的系统架构&#xff0c;包括整体架构设计…