再识C语言 DAY13 【递归函数(超详细)】
文章目录
- 前言
- 一、函数递归
- 什么是递归
- 递归的两个重要条件
- 练习一
- 练习二
- ==递归与迭代==
- 练习三
- 练习四
- ==在练习三、四中出现的问题==
- 如果您发现文章有错误请与我留言,感谢
前言
本文总结于此文章
一、函数递归
什么是递归
函数调用自身的编程技巧称为递归
(函数自己调用自己)
递归分为**递推和回归**
递归的策略
它通常把一个大型复杂的问题层层转换为一个与原问题相似的小问题来解决。
递归的重要思想:把大事化小
例如(史上最简单的递归):
#include<stdio.h>
int main()
{printf("Hello World\n");main();
}
先一直打印 Hallo World,最终程序挂掉
递归的两个重要条件
因当存在限制条件,当满足这个限制条件时递归便不再继续。
每次递归调用之后越来越接近这个限制条件。
练习一
接受一个整型值(无符号),按顺序打印他的每一位
例如:
输入:1234,输出 1 2 3 4
我们的第一想法就是:
1234%10 = 41234/10=123123%10=3123/10=1212%10=212/10=11%10=11/10=0
这样我们能得到数字的每一位,然后我们把他们打印出来
#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
int main()
{int a ,n;printf("请输入一个无符号的整型:");scanf("%d", &a);
while(a>10){if(a>10){n = a % 10;printf("\n%d ",n);a = a / 10;}
}printf("\n%d",a);return 0;
}
我们发现输出结果和题目中的不同,这个问题需要我们用递归来进行
因为递归的原理是先递推再回归,一层一层的传递下去
我们定一个print函数,它的功能是按照顺序打印num的每一位。
打印1234的每一位:print(1234)
打印1234的每一位,我们可以先打印123的每一位再打印4
打印123的每一位:我们可以先打印12的每一位print(12)再打印3
打印12的每一位:我们可以先打印1的每一位print(1)再打印2
最后输出打印1 2 3 4
程序:
print(1234)
print(123) 4
print(12) 3 4
print(1) 2 3 4
最终输出:1 2 3 4
在写代码的过程中,我们只需要关注最后一层的递推和回归
我们的想法就是先把余的1打印出来,再把上一层余的2打出来,以此类推。
此时我们的n等于1 ,用来打印余1
printf("%d ",n%10);
因为这是我们上一层所调用的print函数,当这个函数执行完后,我们还要回到上一层,继续执行代码
此时n等于12,打印出来的结果为2。
printf("%d ",n%10);
依次循环,这就是我们的递归
首先,我们先把递归函数写出来
void print(int n){if(n<10){printf("%d ",n);}else{print(n/10);printf("%d ",n%10); }
}
代码实现:
#include <stdio.h>void print(int n){if(n<10){printf("%d ",n);}else{print(n/10);printf("%d ",n%10); }
}int main (){ int a=0;printf("输入一个数字\n");scanf("%d",&a);print(a);return 0;
}
当然也可以更简便:
其更简便的最根本的原因是限制条件不同,使用n>9时,就不用使用else
#include<stdio.h>
void print(unsigned int n)
{if (n > 9)限制条件{print(n / 10);每次递归调用之后越来越接近这个限制条件}printf("%d ", n % 10);
}
int main()
{unsigned int num = 0;scanf("%u", &num);print(num);return 0;
}
练习二
写一个可以求字符串长度的代码(老朋友了已经是)
我们有一个专门求字符串长度的库函数 strlen
长度等于开始到空字符之间的字符数(不包括空字符本身)\0
首先我们先创建一个字符数组
char arr[] = "abc";
再用strlen函数
#include<stdio.h>
#include<string.h>
int main()
{char arr[] = "abc";strlen(arr);printf("%d", strlen(arr));return 0;
}
我们自己创建一个函数,模仿写一个strlen函数
这里先用非递归方式
#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
int my_strlen(char* str)
{int count = 0;while (*str != '\0'){count++;str++;}return count;
}int main(){char i[100];printf("请输入一个字符串: ");scanf("%s", i);my_strlen(i);printf(" %d", my_strlen(i));return 0;
}
count在这里只是起到一个计数器的作用
如果不太理解指针和数组,下面其辅助作用
int *p1 = &a;
int *p2 = &b;
int *p3 = &c;
int *p4 = &d;
arry[0] = &a;
arry[1] = &b;
arry[2] = &c;
arry[3] = &d;
下来试一下递归
如果第一个字符不是\0,那说明字符串里至少有一个字符
这就是我们的思路
****所以当第一个元素不是’\0’的话
求my_strlen(“abc”)就可以看成求1+my_strlen(“bc”)的长度
求1+my_strlen(“bc”)的长度就可以看成 求1+1+my_strlen(“c”)的长度
求1+1+my_strlen(“c”)的长度就可以看成 求1+1+1+my_strlen(" ")的长度,最后我们让my_strlen(“\0 ”)输出为零就行了
最后算出来等于3
首先写递归函数:
int my_strlen(char* str)
{if(*str !='\0'){return 1 + my_strlen(str+1);}else{return 0;}
}
递归过程如下
代码如下
递归与迭代
练习三
求n的阶乘的和
先构思好递归(思路如下,是别的博主的图,博主文章在前言)
代码实现
#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
int my(int i)
{if(i<=1){return 1;}else{return i *my(i -1);}
}int main(){int i;printf("请输入一个数字: ");scanf("%d", &i);my(i);printf("%d", my(i));return 0;
}
但当数字变大时,递归会算不出结果
递归函数也只是一种解决问题的技巧,它和其它技巧一样,也存在某些缺陷,具体来说就是:递归函数的时间开销和内存开销都非常大,极端情况下会导致程序崩溃。
所以这道题最好用非递归的方式来计算,比如迭代,循环是一种迭代
练习四
求第N个斐波那契数列
什么是斐波那契数列
流程如下:
写出代码:
#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
int Fib(int n)
{if(n<=2){return 1;}else{return Fib(n-1)+Fib(n-2);}
}
int main()
{int n = 0;scanf("%d",&n);printf("%d",Fib(n));return 0;
}
在练习三、四中出现的问题
我们会出现这样的问题
-在使用 Fib 这个函数的时候如果我们要计算第50个斐波那契数字的时候特别耗费时间。
-使用my函数求10000的阶乘(不考虑结果的正确性),程序会崩溃。
原因是因
函数在调用过程中很多计算,其实一直在重复
系统分配给程序的栈空间是有限的,但是如果出现了死循环,或者(死递归),这样有可能导致一直开辟栈空间,最终产生栈空间耗尽的情况,这样的现象我们称为栈溢出
如何解决这个问题
1. 将递归改写成非递归。
2. 使用static全局静态对象替代 nonstatic 局部对象。在递归函数设计中,可以使用 static 对象替代nonstatic 局部对象(即栈对象),这不仅可以减少每次递归调用和返回时产生和释放 nonstatic 对象的开销,而且 static 对象还可以保存递归调用的中间状态,并且可为各个调用层所访问
————————————————
原文链接:https://blog.csdn.net/m0_68468727/article/details/126466506
#include<stdio.h>
int Fib(int n)
{int a = 1;int b = 1;int c = 1;while (n>2){c = a + b;a = b;b = c;//都向后传第一位n--;}return c;
}int main()
{int n = 0;scanf("%d", &n);printf("%d\n", Fib(n));return 0;
}
提示
1. 许多问题是以递归的形式进行解释的,这只是因为它比非递归的形式更为清晰。
2. 但是这些问题的迭代实现往往比递归实现效率更高,虽然代码的可读性稍微差些。
3. 当一个问题相当复杂,难以用迭代实现时,此时递归实现的简洁性便可以补偿它所带来的运行时开销
如果您发现文章有错误请与我留言,感谢
相关文章:

再识C语言 DAY13 【递归函数(超详细)】
文章目录 前言一、函数递归什么是递归递归的两个重要条件练习一练习二 递归与迭代练习三练习四在练习三、四中出现的问题 如果您发现文章有错误请与我留言,感谢 前言 本文总结于此文章 一、函数递归 什么是递归 函数调用自身的编程技巧称为递归 (函数自…...

【Linux】权限管理
🔥博客主页: 小羊失眠啦. 🎥系列专栏:《C语言》 《数据结构》 《C》 《Linux》 《Cpolar》 ❤️感谢大家点赞👍收藏⭐评论✍️ 文章目录 一 、Linux中的用户1.1 Linux用户分类1.2 用户转换1.3 指令提权 二、Linux权限管…...

地理坐标系、空间坐标系、epsg查询网站
坐标系可用范围和详细信息的查询网站 简介 epsg.ruiduobao.com是一个可以查询gdal中所有坐标系信息的网站,可查询到坐标系的基准面、椭球体、中央子午线等相关信息,并对每个坐标系的可用范围在地图中进行了显示。详细信息可以看操作视频: e…...

docker 容器指定主机网段
docker 容器指定主机网段。 使用macvlan网络模式可以让Docker容器直接连接到物理网络,而不需要通过NAT或端口映射的方式来访问它们。可以提高网络性能和稳定性,同时也可以使容器更易于管理。 1、查询网卡的名称:使用ifconfig命令查看网卡名…...

零基础Vue框架上手;git,node,yarn安装
项目搭建环境: git安装:Git - 安装 Git (git-scm.com)(官网) 下载路径:Git - Downloading Package (git-scm.com);根据自己电脑下载相对应的安装包 点next 点next,点到最后安装就行。…...

十分钟学会用springboot制作微信小程序富文本编辑器
1.1 富文本模型设计 在构建富文本编辑器系统时,首先需要设计一个合适的富文本模型。 CREATE TABLE IF NOT EXISTS rich_texts (id INT PRIMARY KEY AUTO_INCREMENT,title VARCHAR(255),content TEXT,created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );这个表包括…...
【BBF系列协议】TR181-1 TR069的设备数据模型
TR-069的TR-181设备数据模型 执行摘要 TR-181定义了TR-069 [2]设备数据模型的版本1(设备:1)。设备:1数据模型仅适用于启用TR-069的终端设备,不适用于互联网网关设备或其他网络基础设施设备。启用TR-069的基础设施设备改为使用TR-098 [4]互联网网关设备数据模型或未来设备…...
Elasticsearch(简称ES)性能优化 实践
Elasticsearch(简称ES)性能优化主要包括以下几个方面: 索引优化: 选择合适的分片数:根据业务需求和数据量合理设置分片数,避免过多或过少分片造成性能问题。分片数过多会导致创建分片速度变慢、集群易崩溃…...
《跨越阶层,小白选专业的逻辑:揭秘家庭背景与个人发展的秘密联系》
文章目录 底层最好的专业 小康最好的专业 中产最好的专业 巨富最好的专业 总结 一个人选专业选的好不好,不在于专业本身,而在于你的出身,你的起点,你的家庭;你需要读懂你的原生家庭的文化才能改变自己。换句话说就是&a…...
Python调用pyspark报错整理
前言 Pycharm配置了SSH服务器和Anaconda的python解释器,如果没有配置可参考 大数据单机学习环境搭建(8)Linux单节点Anaconda安装和Pycharm连接 Pycharm执行的脚本 执行如下 pyspark_model.py 的python脚本,构建SparkSession来执行sparksql "&qu…...

快递员的烦恼 - 华为OD统一考试
OD统一考试(C卷) 分值: 200分 题解: Java / Python / C 题目描述 快递公司每日早晨,给每位快递员推送需要淡到客户手中的快递以及路线信息,快递员自己又查找了一些客户与客户之间的路线距离信息࿰…...

css1基础选择器
大纲 一.标签选择器 比较简单,前面直接写目标标签 二.类选择器 应用 例子 三.多类名选择器(调用时中间用空格隔开) 四.id选择器 应用 五.通配符选择器 应用 六.总结...
【C语言】内联函数总结
内联函数定义 inline关键字是C99标准的型关键字,其作用是将函数展开,把函数的代码复制到每一个调用处。这样调用函数的过程就可以直接执行函数代码,而不发生跳转、压栈等一般性函数操作。可以节省时间,也会提高程序的执行速度。 …...

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之MenuItemGroup组件
鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之MenuItemGroup组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、MenuItemGroup组件 该组件用来展示菜单MenuItem的分组。 子组件 无 接…...
【Linux多线程编程】互斥锁及其使用
1、互斥锁 用于解决竞争问题的一种机制。 什么是竞争,竞争就是多个实体同时获取一个资源,例如多个线程写一个全局变量。 2、Linux如何使用互斥锁 以pthread为例,锁的创建和使用如下: /* 创建锁 */ pthread_mutex_t lock PTHR…...

RabbitMQ_00000
MQ的相关概念 RabbitMQ官网地址:https://www.rabbitmq.com RabbitMQ API地址:https://rabbitmq.github.io/rabbitmq-java-client/api/current/ 什么是MQ? MQ(message queue)本质是个队列,FIFO先入先出,只不过队列中…...
【linux】docker下homeassistant和nodered安装及配置
1、homeassistant安装 从 Docker Hub 上拉取 Home Assistant 的镜像文件 docker pull homeassistant/home-assistant 是运行 Home Assistant 容器 docker run -id --name"homeassistant" --privileged --restart always -p 8123:8123 -e TZAisa/Shanghai --nethost…...

Qt扩展-muParser数学公式解析
muParser数学公式解析 一、概述1. 针对速度进行了优化2. 支持的运算符3. 支持的函数4. 用户定义的常量5. 用户定义的变量6. 自定义值识别回调7. 其他功能 二、内置函数三、内置二元运算符四、三元运算符五、内置常量六、源码引入1. 源码文件2. 编译器开关1. MUP_BASETYPE2.MUP_…...

【Matplotlib】figure方法之图形的保存
🎈个人主页:甜美的江 🎉欢迎 👍点赞✍评论⭐收藏 🤗收录专栏:matplotlib 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共同学习、交流进…...
数据库管理-第142期 DBA?DBA!(20240131)
数据库管理142期 2024-01-31 数据库管理-第142期 DBA?DBA!(20240131)正文总结 数据库管理-第142期 DBA?DBA!(20240131) 作者:胖头鱼的鱼缸(尹海文)…...

流媒体基础解析:音视频封装格式与传输协议
在视频处理与传输的完整流程中,音视频封装格式和传输协议扮演着至关重要的角色。它们不仅决定了视频文件的存储方式,还影响着视频在网络上的传输效率和播放体验。今天,我们将深入探讨音视频封装格式和传输协议的相关知识。 音视频封装格式 什…...

【Stable Diffusion 1.5 】在 Unet 中每个 Cross Attention 块中的张量变化过程
系列文章目录 文章目录 系列文章目录前言特征图和注意力图的尺寸差异原因在Break-a-Scene中的具体实现总结 前言 特征图 (Latent) 尺寸和注意力图(attention map)尺寸在扩散模型中有差异,是由于模型架构和注意力机制的特性决定的。 特征图和注意力图的尺寸差异原…...
LangChain核心之Runnable接口底层实现
导读:作为LangChain框架的核心抽象层,Runnable接口正在重新定义AI应用开发的标准模式。这一统一接口设计将模型调用、数据处理和API集成等功能封装为可复用的逻辑单元,通过简洁的管道符语法实现复杂任务的声明式编排。 对于面临AI应用架构选择…...

Linux 驱动之设备树
Linux 驱动之设备树 参考视频地址 【北京迅为】嵌入式学习之Linux驱动(第七期_设备树_全新升级)_基于RK3568_哔哩哔哩_bilibili 本章总领 1.设备树基本知识 什么是设备树? Linux之父Linus Torvalds在2011年3月17日的ARM Linux邮件列表…...
Hadoop复习(九)
Azkaban工作流管理器 选择 问题 1 判断题 2 / 2 分 工作流是指具有依赖的一组job任务,被依赖的job任务最后执行 正确 错误 问题 2 判断题 2 / 2 分 Azkaban兼容任何版本的Hadoop 正确 错误 问题 3 判断题 2 / 2 分 独立服务器模式下,Azkab…...
nginx+tomcat动静分离、负载均衡
一、理论 nginx用于处理静态页面以及做调度器,tomcat用于处理动态页面 lvs(四层) 轮询(rr) 加权轮询(wrr) 最小连接(lc) 加权最小连接(wlc) ngi…...

CRM管理软件的数据可视化功能使用技巧:让数据驱动决策
在当今数据驱动的商业环境中,CRM管理系统的数据可视化功能已成为企业优化客户管理、提升销售效率的核心工具。据企销客研究显示,具备优秀可视化能力的CRM系统,用户决策效率可提升47%。本文将深入解析如何通过数据可视化功能最大化CRM管理软件…...

AutoGenTestCase - 借助AI大模型生成测试用例
想象一下,你正在为一个复杂的支付系统编写测试用例,需求文档堆积如山,边缘场景层出不穷,手动编写让你焦头烂额。现在,有了AutoGenTestCase,这个AI驱动的“测试用例生成机”可以从需求文档中自动生成数百个测…...

如何配置mvn镜像源为华为云
如何配置mvn镜像源为华为云 # 查找mvn 配置文件 mvn -X help:effective-settings | grep settings.xml# 配置mvn镜像源为华为云,/home/apache-maven-3.9.5/conf/settings.xml文件路径需要根据上一步中查询结果调整 cat > /home/apache-maven-3.9.5/conf/setting…...

字节新出的MCP应用DeepSearch,有点意思。
大家好,我是苍何。 悄悄告诉你个事,昨天我去杭州参加字节火山方舟举办的开发者见面会了,你别说,还真有点刘姥姥进大观园的感觉🐶 现场真实体验完这次新发布的产品和模型,激动的忍不住想给大家做一波分享。…...