C语言复习笔记--函数递归

news2025/3/29 14:02:46

        在学习了函数之后,函数递归是我们必然会接触到的课题,下面就让我们看下函数递归相关的知识.

递归是什么?

        递归这个词看着就不那么好理解,那么什么是递归呢?递归其实是⼀种解决问题的⽅法,在C语⾔中,递归就是函数自己调用自己.

        写⼀个史上最简单的C语⾔递归代码:

int main()
{
	printf("hehe\n");
	main();
	return 0;
}

        尽管这个代码可以跑起来,但是在跑一会后就会出现下面的现象.在报错栏可以看到如递归所有控件路径,函数将导致运行时堆栈溢出的字.所以这串代码只起到了演示作用毫无解决问题意义.

        当然通过今天的简单学习是还不足以掌握函数递归的.在之后的学习中,特别是数据结构中我们会常用到这方面的知识.那时在进一步熟悉使用.

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

递归的限制条件

        为了避免像上面演示代码一样的无限递归导致栈溢出现象.递归在书写的时候,有2个必要条件:

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

        2.每次递归调用之后越来越接近这个限制条件.

递归举例

  举例1:求n的阶乘

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

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

        这样的思路就是把⼀个较⼤的问题,转换为⼀个与原问题相似,但规模较⼩的问题来求解的。 n!---> n*(n-1)! (n-1)! ---> (n-1)*(n-2)!.......直到n是1或者0时,不再拆解.这样就可以得到递推函数式.

        然后我们就可以尝试写出代码了.

//计算n的阶乘(不考虑溢出),n的阶乘就是1~n的数字累积相乘
int Fuc(int a)
{
	if (0 == a)
	{
		return 1;
	}
	else
	{
		return Fuc(a - 1) * a;
	}
}
int main()
{
	int a = 0;
	scanf("%d", &a);
	printf("%d\n",Fuc(a));
	return 0;
}
//注:这⾥不考虑n太⼤的情况,n太⼤存在溢出

         我们可以从递推演示图中更好地了解这个函数的递推过程.

  举例2:顺序打印⼀个整数的每⼀位

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

⽐如:

输⼊:1234 输出:1 2 3 4

输⼊:520 输出:5 2 0

        我们可以发现每个数的最后一位是最容易拿到的.进一步用递归的思想思考我们可以得:到打印1234的每一位可以转化为打印123每一位然后在打印4.我讲这个函数命名为Print,就可以得到下面的表达式.

        这样就可以写出代码了.

//输⼊⼀个整数m,打印这个按照顺序打印整数的每⼀位。
void Print(int a)
{
	if (a > 9)
	{
		Print(a / 10);
		printf("%d ", a % 10);
	}
	else
	{
		printf("%d ", a);
	}
}
int main()
{
	int a = 0;
	scanf("%d", &a);
	Print(a);
	return 0;
}

        通过 上面两个例子,简单地说下我在递归中常犯的错误:如果递归函数有返回值那么需要写return后面写函数自己,如果返回值为void,那么直接调用函数即可,不要写return.

递归与迭代

        递归是⼀种很好的编程技巧,但是很多技巧⼀样,也是可能被误⽤的,就像举例1⼀样,看到推导的公式,很容易就被写成递归的形式.Fact函数是可以产⽣正确的结果,但是在递归函数调⽤的过程中涉及⼀些运⾏时的开销.也就是在上面代码中备注的,如果输入过大就会造成递归太深而栈溢出.(这里涉及到函数栈帧的问题,关于函数栈帧的详细内容见博客C语言复习笔记--函数栈帧创建与销毁-CSDN博客).

        所以如果不想使⽤递归就得想其他的办法,通常就是迭代的⽅式(通常就是循环的⽅式).下面就用迭代的方式来解决下举例1.

int main()
{
	int a = 0;
	int n = 1;
	scanf("%d", &a);
	for (int i = 1; i <= a; i++)
	{
		n *= i;
	}
	printf("%d ", n);
	return 0;
}

        事实上,我们看到的许多问题是以递归的形式进⾏解释的,这只是因为它⽐⾮递归的形式更加清晰, 但是这些问题的迭代实现往往⽐递归实现效率更⾼.下面再来看一个例子

  举例3:求第n个斐波那契数

就像计算第n个斐波那契数

        看到这公式,很容易诱导我们将代码写成递归的形式,如下所⽰:

int Fib(int a)
{
	if (1 == a || 2 == a)
	{
		return 1;
	}
	else
	{
		return Fib(a - 1) + Fib(a - 2);
	}
}
int main()
{
	int a = 0;
	scanf("%d", &a);
	int n = Fib(a);
	printf("%d ", n);
	return 0;
}

        但是当输入的a变大之后这个程序跑出结果变得非常慢.因为递归需要重复计算好多数值.如图下所示,(同种颜色都是重复计算)所以这个问题更适合用迭代去解决.

//迭代
int Fib(int a)
{
	int x = 1;
	int y = 1;
	int z = 0;
	for (int i = 3; i <= a; i++)
	{
		z = x + y;
		x = y;
		y = z;
	}
	return z;
}
int main()
{
	int a = 0;
	scanf("%d", &a);
	int n = Fib(a);
	printf("%d ", n);
	return 0;
	return 0;
}

        迭代的⽅式去实现这个代码,效率就要⾼出很多了.递归虽好,但是也会引⼊⼀些问题,我们要适当使用. 

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

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

相关文章

husky的简介以及如果想要放飞自我的解决方案

husky 是一个 Git Hooks 管理工具&#xff0c;它的主要作用是 在 Git 提交&#xff08;commit&#xff09;、推送&#xff08;push&#xff09;等操作时执行自定义脚本&#xff0c;比如代码检查&#xff08;Lint&#xff09;、单元测试&#xff08;Test&#xff09;、格式化代码…

侯捷 C++ 课程学习笔记:现代 C++ 中的移动语义与完美转发深度解析

1. 前言&#xff1a;为什么我们需要移动语义&#xff1f; 在侯捷老师的《C11/14/17 新特性详解》课程中&#xff0c;移动语义&#xff08;Move Semantics&#xff09;被称作"C近十年来最重要的革新"。传统C中饱受诟病的深拷贝性能问题&#xff0c;在现代C中通过移动语…

23种设计模式-结构型模式-适配器

文章目录 简介场景问题解决方案建立中间转换层关键收益 总结 简介 使接口不兼容的类实现协同工作&#xff0c;通过引入中间层实现客户端接口和服务端接口的兼容。典型场景比如整合第三方类库或遗留系统时保持代码兼容。 场景 假设你正在开发一个股票监控程序。这个程序会下…

美亚科技业绩波动明显:现金流为负,四起未决诉讼涉金额1700万

《港湾商业观察》施子夫 近期&#xff0c;广东美亚旅游科技集团股份有限公司&#xff08;以下简称&#xff0c;美亚科技&#xff09;披露第二轮审核问询函的回复。从两轮问询函监管层提出的问题来看&#xff0c;有关美亚科技业绩增长的合理性、募投项目的必要性及合理性、经营…

PyTorch 深度学习实战(21):元强化学习与 MAML 算法

一、元强化学习原理 1. 元学习核心思想 元强化学习&#xff08;Meta-RL&#xff09;旨在让智能体快速适应新任务&#xff0c;其核心是通过任务分布学习共享知识。与传统强化学习的区别在于&#xff1a; 对比维度传统强化学习元强化学习目标解决单一任务快速适应任务分布中的…

23中设计模式-迭代器(Iterator)设计模式

迭代器设计模式 &#x1f6a9;什么是迭代器设计模式&#xff1f;&#x1f6a9;迭代器设计模式的特点&#x1f6a9;迭代器设计模式的结构&#x1f6a9;迭代器设计模式的优缺点&#x1f6a9;迭代器设计模式的Java实现&#x1f6a9;代码总结&#x1f6a9;总结 &#x1f6a9;什么是…

Word中公式自动标号带章节编号

&#xff08;1&#xff09;插入一行三列的表格&#xff0c;设置宽度分别为0.5&#xff0c;13.39和1.5&#xff0c;设置纵向居中&#xff0c;中间列居中对齐&#xff0c;最右侧列靠右对齐&#xff0c;设置段落如下 &#xff08;2&#xff09;插入域代码 【Word】利用域代码快速实…

【Spring AI】基于专属知识库的RAG智能问答小程序开发——功能优化:用户鉴权主体功能开发

系列文章目录 【Spring AI】基于专属知识库的RAG智能问答小程序开发——完整项目&#xff08;含完整前端后端代码&#xff09;【Spring AI】基于专属知识库的RAG智能问答小程序开发——代码逐行精讲&#xff1a;核心ChatClient对象相关构造函数【Spring AI】基于专属知识库的R…

[7-01-03].SpringBoot3集成MinIo

MinIO学习大纲 一、Spingboot整合MinIo 第1步&#xff1a;搭建SpringBoot项目&#xff1a; 第2步&#xff1a;引入minio依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi&q…

ISIS-3 LSDB链路状态数据库同步

上一章我们介绍了ISIS的邻居建立关系以及ISIS的路由器角色有哪些,在不同的网络类型当中建立邻居关系有什么不同,并且以实验案例抓包的形式给大家进一步介绍了建立的过程。 这一章我们来介绍ISIS中是如何实现链路状态数据库同步的,与OSPF的链路状态同步有什么不同,在不同网络类…

快速入手-基于Django的Form和ModelForm操作(七)

1、Form组件 2、ModelForm操作 3、给前端表单里在django里添加class相关属性值 4、前端 5、后端form 新增数据处理 6、更新数据处理

Springboot集成Debezium监听postgresql变更

1.创建springboot项目引入pom <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>io.debezium</groupI…

Ubuntu22.04搭建freeradius操作说明

Ubuntu22.04搭建freeradius操作说明 更新依赖库 sudo apt update sudo apt install build-essential sudo apt install libtalloc-dev sudo apt install libssl-dev 按照freeradius sudo apt install freeradius 修改freeradius配置 文件路径如下 /etc/freeradius/3.…

【重装系统】全流程记录,在 MacOS 的电脑上烧录 Ubuntu 启动盘

背景 Ubuntu 无法联网&#xff0c;排查下来应该是网卡驱动的问题&#xff0c;安装驱动的过程中又缺失各种包需要网络&#xff0c;陷入死循环。 全流程以及相关资料 整体流程参考&#xff1a;【史上最全】重装ubuntu20.04系统基本环境配置 烧录启动盘启动盘插入需要重装的服务…

去中心化金融

什么是去中心化金融 去中心化金融&#xff08;Decentralized Finance&#xff0c;简称 DeFi&#xff09;是一种基于区块链技术构建的金融系统&#xff0c;旨在通过去除传统金融机构&#xff08;如银行、证券公司等&#xff09;作为中介&#xff0c;提供各种金融服务。这些服务…

centos 7 部署FTP 服务用shell 脚本搭建

#!/bin/bash# 检查是否以root身份运行脚本 if [ "$EUID" -ne 0 ]; thenecho "请以root身份运行此脚本。"exit 1 fi# 安装vsftpd yum install -y vsftpd# 启动vsftpd服务并设置开机自启 systemctl start vsftpd systemctl enable vsftpd# 配置防火墙以允许F…

VMware启动虚拟机报“另一个程序已锁定文件的一部分,进程无法访问”

解决方案&#xff1a; 1&#xff09;定位到虚拟机磁盘目录&#xff0c;我这里是“E\VM_Disk\CactiEZ\”这个目录&#xff0c;每个人目录不一样&#xff0c;详见上图报错位置 2&#xff09;在这个目录中找到后缀名以“.lck”结尾的目录&#xff0c;将所有以 .lck 结尾的目录删…

CPU架构和微架构

CPU架构&#xff08;CPU Architecture&#xff09; CPU架构是指处理器的整体设计框架&#xff0c;定义了处理器的指令集、寄存器、内存管理方式等。它是处理器设计的顶层规范&#xff0c;决定了软件如何与硬件交互。 主要特点&#xff1a; 指令集架构&#xff08;ISA, Instr…

帕金森病致生活艰难,如何缓解心理负担?

你是否留意到身边有人手部不由自主地颤抖&#xff0c;且肢体变得僵硬&#xff0c;行动也愈发迟缓&#xff1f;这很可能是帕金森病的症状。帕金森病是一种常见的神经系统退行性疾病&#xff0c;多发生于中老年人。​ 静止性震颤往往是帕金森病的首发症状&#xff0c;患者在安静状…

[Windows] Edge浏览器_134.0.3124.83绿色便携增强版-集成官方Deepseek侧边栏

微软Edge浏览器 绿色便携增强版 长期更新 链接&#xff1a;https://pan.xunlei.com/s/VOMA-aVC_GPJiv-MzRS89lsVA1?pwdemxj# Edge浏览器_134.0.3124.83绿色便携增强版-集成官方Deepseek侧边栏