c语言基础知识帮助理解(函数递归详解)

"从前有座山,山里有座庙,庙里有个老和尚和一个小和尚。有一天老和尚对小和尚说:“从前有座山.山里有座庙,庙里有个老和尚和一个小和尚,有一天老和尚对小和尚说:“从前有座山.山里有座庙,庙里有个老和尚和一个小和尚......" (虽能体现递归特点,但又不是递归)


目录

1.什么是递归

2.递归的两个必要条件

 3.事例和讲解

 4.递归原理讲解

 5.递归弊端

5.1利用计算斐波那契数列来引入

5.2如何改进 


1.什么是递归

当一个函数在其定义中调用自身的过程称为递归。递归是一种强大的编程技巧,可以解决许多问题,特别是那些可以被分解为相同问题的子问题的情况

递归的主要思考方式在于:把大事化小

在C语言中,函数递归的基本原理是将一个大问题分解为一个或多个更小的问题,然后通过调用自身来解决这些更小的问题,直到达到基本情况,即不再需要递归调用的情况 


2.递归的两个必要条件

  • 存在限制条件,当满足这个限制条件的时候,递归便不再继续。
  • 每次递归调用之后越来越接近这个限制条件。

试想如若没有限制条件,那便无限循环,真就成了上面的“从前有座山 山里有座庙” 的故事了。


 3.事例和讲解

用递归来实现求n的阶乘(factorial) :

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int factorial(int n)
{
	if (n > 1)//递归终止的条件
	{
		return n * factorial(n - 1);
	}
	else
	{
		return 1;
	}
}

int main()//递归实现求n的阶乘
{
	int n = 0;
	scanf("%d", &n);
	int n_factorial = factorial(n);
	printf("%d", n_factorial);
	return 0;
}

下面是一个示例的递归树,用于说明计算4的阶乘的过程:

4! = 4 * 3!

|

3! = 3 * 2!

|

2! = 2 * 1!

|

1! = 1

下面讲解一下思路:

  • 最基本便是:n!=n*(n-1)!——让我们有了返回n * factorial(n - 1)的想法
  • 当n=1时,便是终止条件——返回1 ,使用factorial(n - 1)也是为了更加靠近n=1的终止条件

 4.递归原理讲解

当一个函数被调用时,会在内存中分配一个称为函数栈帧(Function Stack Frame)的数据结构。函数栈帧用于存储函数的局部变量、函数的参数、函数的返回地址等信息。

下面是一个示意图,展示了函数栈帧的结构:

  •  Return Address:保存着函数调用结束后需要返回的地址,即函数调用的下一条指令的地址。当函数执行完毕后,CPU会根据该地址跳转到正确的位置继续执行
  • Previous Stack Frame:指向调用函数的函数栈帧的地址,用于在函数返回时恢复调用函数的上下文
  • Local Variables:存储函数的局部变量。每个函数栈帧都有自己的一块内存空间,用于存储局部变量的值
  • Parameters:存储函数的参数。参数在函数调用时被传递给函数,并存储在函数栈帧中

在递归函数中,每次递归调用都会生成一个新的函数栈帧,这些函数栈帧会按照一定的顺序依次排列在内存中:先调用的函数先进入栈中,后销毁

 


 5.递归弊端

5.1利用计算斐波那契数列来引入

int Fib(int n)
{
	if (n <= 2)
		return 1;
	else
		return Fib(n - 1) + Fib(n - 2);
}

int main()
{
	int n = 3;
	printf("第三个斐波那契数%d\n", Fib(n));

	int x = 50;
	printf("第五十个斐波那契数%d", Fib(x));
	return 0;
}

 我们会发现,第三个斐波纳契数立马就出来了,而第五十个迟迟不出来。

这就暴露了问题:

  • 这个函数的时候如果我们要计算第 50 个斐波那契数字的时候特别耗费时间
  • 函数求 10000 的阶乘(不考虑结果的正确性),程序会崩溃(我已经为各位试过了,不要再试了),也就是栈溢出了

这也说明:有时递归的效率不是很高 ,而且不得不说有时递归代码的可读性是不及循环的

5.2如何改进 

 那我们如何改进呢?

  • 将递归改写成非递归。
  • 使用static对象替代 nonstatic 局部对象。在递归函数设计中,可以使用 static 对象替代nonstatic 局部对象(即栈对象),这不仅可以减少每次递归调用和返回时产生和释放 nonstatic 对象的开销,而且 static 对象还可以保存递归调用的中间状态,并且可为各个调用层所访问

下面便用循环来改写求斐波那契数列:

int Fib(int n)
{
	int n1 = 1;
	int n2 = 1;
	int result = 0;
	while (n > 2)
	{n--;
		result = n1 + n2;
		n1 = n2;
		n2 = result;
		
	}
	return result;
}

int main()
{
	int n = 3;
	printf("第三个斐波那契数%d\n", Fib(n));

	int x = 30;
	printf("第三十个斐波那契数%d", Fib(x));
	return 0;
}

所以我们也不要一味地去使用递归在合适的代码里使用合适的方法才能让我们的编程水平更加出色。 


总之,递归是一项强大的编程技术,但在使用时需要注意栈溢出问题。通过合理的算法设计和对函数栈帧的了解,我们可以更好地应对递归问题,使代码更加健壮和可靠

这次的分享先到这里的,感谢大家的支持,下一次会总结数组相关的知识!!! 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序tab加列表demo

一、效果 代码复制即可使用&#xff0c;记得把图标替换成个人工程项目图片。 微信小程序开发经常会遇到各种各样的页面组合&#xff0c;本demo为list列表与tab组合&#xff0c;代码如下&#xff1a; 二、json代码 {"usingComponents": {},"navigationStyle&q…

Github Pages自定义域名

Github Pages自定义域名 当你想在网上发布内容时&#xff0c;配置Github Pages是一个很好的选择。如果你想要在自己的域名上发布&#xff0c;你可以使用Github Pages来创建自己的网站。本文将介绍如何使用Github Pages自定义域名。 这里呢先列出前置条件&#xff1a; 您的Gi…

【无公网IP】在公网环境下Windows远程桌面Ubuntu 18.04

【无公网IP】在公网环境下Windows远程桌面Ubuntu 18.04 文章目录 【无公网IP】在公网环境下Windows远程桌面Ubuntu 18.04一、 同个局域网内远程桌面Ubuntu1. 更新软件仓库2. 安装支持包3. 安装XFCE4桌面环境4. 安装XRDP5. 环境设置5.1 XFCE桌面配置5.2 在配置文件中&#xff0c…

防雷工程行业应用和施工工艺

防雷工程是指通过各种手段和措施&#xff0c;保护建筑物、设备和人员免受雷电侵害的技术。在我国&#xff0c;由于雷电活动频繁&#xff0c;防雷工程的重要性不言而喻。地凯科技将介绍防雷工程的基本知识、相关案例以及防雷器产品。 一、防雷工程的基本知识 雷电的危害 雷电…

浅谈下API初步认知

当我们谈论API&#xff0c;我们指的是应用程序接口&#xff08;Application Programming Interface&#xff09;。API允许不同的软件应用程序之间互相通信和交互。它定义了一组规定和协议&#xff0c;用于确定数据传输和请求的格式、方法和功能。 API的作用是在软件开发中提供一…

LeetCode--HOT100题(19)

目录 题目描述&#xff1a;54. 螺旋矩阵&#xff08;中等&#xff09;题目接口解题思路代码 PS: 题目描述&#xff1a;54. 螺旋矩阵&#xff08;中等&#xff09; 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 Le…

企业服务器中了Locked勒索病毒后怎么办,如何解决问题并提高防范意识

科学技术的发展给我们的生活带来了极大便利&#xff0c;但也为企业带来了安全威胁。近期&#xff0c;我们收到很多企业的求助&#xff0c;企业的服务器中了locked后缀勒索病毒&#xff0c;计算机上的所有文件都被加密&#xff0c;无法被正常调取&#xff0c;严重影响了企业的正…

Linux第六章之vim与gcc使用

一、Linux编辑器-vim使用 vi/vim的区别简单点来说&#xff0c;它们都是多模式编辑器&#xff0c;不同的是vim是vi的升级版本&#xff0c;它不仅兼容vi的所有指令&#xff0c;而且还有一些新的特性在里面。例如语法加亮&#xff0c;可视化操作不仅可以在终端运行&#xff0c;也…

Kotlin基础(十):函数进阶

前言 本文主要讲解kotlin函数&#xff0c;之前系列文章中提到过函数&#xff0c;本文是kotlin函数的进阶内容。 Kotlin文章列表 Kotlin文章列表: 点击此处跳转查看 目录 1.1 函数基本用法 Kotlin 是一种现代的静态类型编程语言&#xff0c;它在函数的定义和使用上有一些特点…

2023年第四届“华数杯”数学建模思路 - 案例:最短时间生产计划安排

文章目录 0 赛题思路1 模型描述2 实例2.1 问题描述2.2 数学模型2.2.1 模型流程2.2.2 符号约定2.2.3 求解模型 2.3 相关代码2.4 模型求解结果 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; 最短时间生产计划模型 该模型出现在好几个竞赛赛题上&#x…

【心电图信号压缩】ECG信号压缩与通过三次样条近似重建的ECG信号压缩研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

SpringCloudAlibaba之Nacos配置中心

第一步&#xff1a;引入jar包 <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> 第二步&#xff1a;在resources下创建一个bootstrap.yml文档…

HTTP杂谈之Referer和Origin请求头再探

一 关于Referer和Origin的汇总 1) 知识是凌乱的,各位看官看个热闹即可2) 内容不断更新1、理解有盲区,需要及时纠正2、内容交叉有重复,需要适当删减3、扩展视野3) 以下内容都与Referer和Origin请求头有关联 nginx防盗链 HTTP杂谈之Referrer-Policy响应头 iframe标签referre…

Windows用户如何将cpolar内网穿透配置成后台服务,并开机自启动?

Windows用户如何将cpolar内网穿透配置成后台服务&#xff0c;并开机自启动&#xff1f; 文章目录 Windows用户如何将cpolar内网穿透配置成后台服务&#xff0c;并开机自启动&#xff1f;前置准备&#xff1a;VS Code下载后&#xff0c;默认安装即可VS CODE切换成中文语言 1. 将…

Linux中的特殊进程(孤儿进程、僵尸进程、守护进程)

一、孤儿进程 1&#xff09;父进程退出&#xff0c;子进程不退出&#xff0c;此时子进程被1号&#xff08;init&#xff09;进程收养&#xff0c;变成孤儿进程。 2&#xff09;孤儿进程会脱离终端控制&#xff0c;且运行在后端&#xff0c;不能用ctrlc杀死后端进程&#xff0c;…

excal中遇到数据变成科学计数法的处理方法

1、单元格宽度太小&#xff08;解决办法增加单元格的宽度&#xff09; 2、通过设置单元格格式里面调整 #;#;0;G/通用格式

Cesium 加载ArcGIS Server切片服务错级问题

1.首先上官方api说明 ArcGisMapServerImageryProvider - Cesium Documentation 里面没有 zoomoffset参数!!! 2.如果按照互联网栅格切片规则 3857、4326、4490常用切片层级参数,则直接加载显示地图 viewer.imageryLayers.addImageryProvider(new Cesium.ArcGisMapServerI…

GPU 容器虚拟化新能力发布和全场景实践

今天给大家分享的主题是百度智能云在「GPU 容器虚拟化」方面的最新进展和全场景实践&#xff0c;希望通过这次分享和大家一起探讨如何在实际业务场景更好的应用 GPU 容器虚拟化技术。 本次分享将首先介绍百度智能云 GPU 容器虚拟化 2.0 的升级变化&#xff0c;然后介绍新版本中…

一元三次方程求解

一元三次方程求解 题目描述提示输入输出格式输入格式输出格式 输入输出样例输入样例输出样例 算法分析A C 代码 题目描述 有形如&#xff1a; a x 3 b x 2 c x d 0 ax^3bx^2c^xd0 ax3bx2cxd0一元三次方程。给出该方程中各项的系数 ( a a a&#xff0c; b b b&#xff0c;…

java环境搭建 Ubuntu Linux

jdk的安装和配置环境变量 使用apt sudo apt install default-jdk若是安装成功了在终端输入java -version来查看是否安装成功 使用官网下载的jdk包 直接在百度上搜索jdk&#xff0c;选择图片这个 网址:jdk下载网址 若是arm就选择带有arm的&#xff0c;反之选择x64的&#…