函数递归

news2024/11/26 14:47:54

哈喽啊各位,真是,好久好久好久不见。这段时间实在是太过忙碌了昂,还望诸君见谅,接下来时间会松很多,咱们也会恢复正常更新速度啦

小希在这里祝诸君:期末不挂科,四六级都过!功不唐捐,玉汝于成!!!

今天昂,咱们来认识认识函数递归

一 . 什么是递归?

在我们的C语言中,“ 递归 ”是我们相当重要的一环,简而言之,递归就是——函数自己调用自己。这是一种高效解决问题的办法。

这里为诸君演示一个最简单的递归函数:

在main函数中调用main函数:

因为我们没有终止信息,程序就会一直调用,一直打印

这里代码最终会陷入死递归,导致栈溢出(Stack overflow)

在这里只是为了给诸君演示一下递归的基本形式,不是为了解决任何实际问题

二 . 递归的本质

在递归中:“ 递 ” 就是 “ 递推 ”,“ 归 ” 就是 “ 回归 ”

递归的本质就是,把一个大型复杂的问题层层转化为一个与原问题相似,但规模较小的子问题来求解,一直拆分到子问题不能再被拆分,递归就结束了。所以递归的思考方式就是将大事化小的过程

三 . 递归的限制条件

递归在书写的时候,有两个必要条件:  
(1) 递归存在限制条件,当满足这个限制条件的时候,递归便不再继续 
(2) 每次递归调用之后越来越接近这个限制条件

 四 . 递归举例

(1)计算 n 的阶乘 n!(不考虑溢出)

注意:一个正整数的阶乘(factorial)就是所有小于等于该数的正整数的乘积,且规定0的阶乘为1

因为我们知道,n 的阶乘公式为:n!= n * (n - 1)!,如:

又因为 0 的阶乘为 1 ,则当 n == 0 时,n 的阶乘为 1 

由此我们可以得出计算时的两种情况:

那么接下来我们就可以来实现这个阶乘函数:

画图演推:

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

例如:输入1234,打印1 2 3 4 

分析:如果n是一位数,n的每一位就是n自己,n是超过1位数的话,就得拆分每一位

1234%10就能得到4,然后1234/10得到123 ,这就相当于去掉了4 ,然后继续对123%10,就得到了3,再除10去掉3,以此 类推不断的 %10 和 /10 操作 ,直到1234的每⼀位都得到
 

但是这样我们就会发现一个问题:我们先得到的总是最低位的数,但题目要求我们需要顺位打印,这个时候我们就可以通过递归实现,先将它 / 10,直到 / 到最前方的一位,再打印,如:

画图推演:

五 . 递归和迭代

递归是一种很好很方便的编程技巧,但是我们需要将其运用在合适的环境下,并不是每一个环境中我们使用递归都会使代码更加简便,搞不好就会弄巧成拙

就如同我们举例的第一道题目,求一个数的阶乘。还记得我们在第一个题目的后面还特别注释了:不考虑栈溢出的问题,这是因为,我们运用递归的确是可以实现求阶乘的运算,但是我们在递归的调用时,会涉及到一些运用时的开销

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

所以在这个题型下,我们最优解应该是采用迭代的方式,也就是我们常说的循环,如:

在这个题型中,我们使用迭代的方式的效率是要高于使用递归的

由此可见,我们递归虽好,但不要滥用哦,只有当一个问题非常复杂,我们难以使用迭代的方式解决问题的时候,此时使用递归的简洁性便可弥补其使用带来的运行时的开销

六 . 斐波那契数

在这里我再来举一个例子来帮助诸君理解递归与迭代

斐波那契数列是什么呢?我这里就直接为诸君搬运百度百科了昂:

简而言之呢,就是这个斐波那契数列,前两项都为 1 ,此后的每一项都等于前两项之和

求第 n 个斐波那契数:

(1)运用递归方式

斐波那契数的运算原理如下,我们可以发现,这不就是我们的递归嘛

当我们求第 n 个斐波那契数的时候,它是不适合用递归的方式来求解的,这个时候就有小伙伴要真诚地发出疑问了:这是为什么呢?明明斐波那契数本身就是通过递归的方式来运算的,我们现在用递归的方式来实现它反而不合适了呢?Good question!!!

诸君不必心急,接下来咱们就先用递归的方式来实现它,我们看看会遇到哪些问题就明白了,毕竟实践才是检验真理的唯一标准嘛

此时我们可以看到,运用递归求求第 n 个斐波那契数没有任何问题,但当我们需要运算的数字非常大时,比如50,这个效率就非常慢昂:

反正我是等了大概3分多钟,有闲心的可以自己等一等哈哈,而且还得出了一个负数,这里应该就是出现了栈溢出的问题昂

通过递归计算效率极其低下的原因是:在我们递归的运行中,会有相当大量的重复计算,且递归的层次越深,冗余计算就会越多

如图,我们要通过递归计算第50个斐波那契数,这是一个倒序的运算过程,我们先要知道第49位的数和第48位数,我们要知道这两位数我们又得先知道第48,47,47,46位,以此类推......

由此可见,我们通过递归来实现它是还会有这非常大量的冗余计算的,所以效率极其低下

(2)运用迭代方式

当我们运用迭代方式来计算效率就高得多,无需多言,咱们直接上图昂:

运用了迭代的方式,没有了冗余的计算,咱们的运算效率就高得多昂,即使是50也是秒出答案

这就是递归和迭代的区别,咱们不能滥用,得根据题目所给出的环境选择合适的方法!

OKK,有关函数递归方面的知识今天咱们就谈到这里了,许久不见,甚是想念,还望各位继续与我一同前行,话不多说,咱们下期再见,与诸君共勉!!!

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

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

相关文章

玩转Word域代码,再也不担心引用多个文献时的排版

文章目录 序列域代码星号和井号多个参考文献交叉引用 在Word中,域代码是一种特殊的文本,可在文档中插入动态内容,而无需手动输入。熟练掌握域代码的基本原理,可以在Word排版时事半功倍。 序列域代码 【CtlF9】会显式出花括号&am…

【一】【QT开发应用】QT开发环境配置,安装QT应用

下载QT软件 点击网址链接,QT下载网址 下载vsaddin插件 点击网址链接,QT下载网址 根据自己的vs版本下载对应的文件. 安装QT 用命令行打开安装程序 找到直接路径, D:\Software\QT\qt-unified-windows-x86-4.3.0-1-online.exe 利用WindowsPowe…

tyflow线相关教程二

线条生长一 生长静脉二 绳索动画三 两个球线连接四 扫帚五

PFA可溶性聚四氟乙烯晶圆盒培养皿一体成型

PFA可溶性聚四氟乙烯晶圆盒培养皿一体成型 PFA培养皿由一个盖子和一个底组成,独特的加工技术,底部圆弧好,经过磨光处理,表面平滑不挂水,无划痕。多用于实验室接种、划线、培养细菌、分离细菌等,尤其是成膜…

RPC框架知识学习

RPC框架介绍 RPC(Remote Procedure Call,远程过程调用)框架是一种允许程序调用位于另一台计算机上的程序的技术。这种调用看起来就像是调用本地程序一样,但实际上是通过网络进行的。RPC框架使得分布式系统的开发变得更加简单&…

简单几步把完整的Windows塞进U盘,小白都能看懂

前言 小白之前写过相似的文章,但教程是通过WinPE操作实现的。 把Windows系统装进U盘,从此到哪都有属于你自己的电脑系统 有些小伙伴反馈教程写得很复杂,简直生涩难懂。 为啥要写得这么复杂呢?小白是想让小伙伴们多了解一些不同…

【尚庭公寓SpringBoot + Vue 项目实战】用户管理(十五)

【尚庭公寓SpringBoot Vue 项目实战】用户管理(十五) 文章目录 【尚庭公寓SpringBoot Vue 项目实战】用户管理(十五)1、业务介绍2、接口实现2.1、根据条件分页查询用户列表2.2、根据ID更新用户状态 1、业务介绍 用户管理共包含两…

++++++局部变量、全局变量及变量的存储类别++++====+++指针+++

局部变量、全局变量及变量的存储类别 局部变量与全局变量的基本概念 局部变量:在函数内部定义的变量称为局部变量,也称为内部变量。它们只在定义它们的函数内部有效,即只有在这个函数被调用时,局部变量才会被分配内存空间&#x…

从根源解决问题:构建体系化BOM管理机制与解决方案

BOM(物料清单)是设计与生产间的纽带,其准确及时对企业的竞争力至关重要。然而,维护BOM数据时,常遇到录入错误、信息孤岛及跨部门沟通障碍等难题,直接影响生产效率和成本。为此,道合顺将探讨确保…

「布道师系列文章」宝兰德徐清康解析 Kafka 和 AutoMQ 的监控

作者|北京宝兰德公司解决方案总监徐清康 01 前言 当我们使用一个软件的时候,经常都会问这个软件怎么监控、监控他的哪些指标?Kafka 的监控挺长时间都是一个老大难的问题,社区在监控方面一直没有投入太大的精力。如果要实现一…

MTANet: 多任务注意力网络,用于自动医学图像分割和分类| 文献速递-深度学习结合医疗影像疾病诊断与病灶分割

Title 题目 MTANet: Multi-Task Attention Network for Automatic Medical Image Segmentation and Classification MTANet: 多任务注意力网络,用于自动医学图像分割和分类 01 文献速递介绍 医学图像分割和分类是当前临床实践中的两个关键步骤,其准…

BRAVE:扩展视觉编码能力,推动视觉-语言模型发展

视觉-语言模型(VLMs)在理解和生成涉及视觉与文本的任务上取得了显著进展,它们在理解和生成结合视觉与文本信息的任务中扮演着重要角色。然而,这些模型的性能往往受限于其视觉编码器的能力。例如,现有的一些模型可能对某…

苹果Mac电脑遭恶意软件攻击 Mac第三方恶意软件删除不了

苹果Mac电脑一直以来都以安全性和稳定性著称,许多用户认为Mac电脑不会受到恶意软件的侵害,但事实上,Mac电脑也不是绝对安全的,近年来,有越来越多的恶意软件针对Mac电脑进行攻击,甚至有些恶意软件可以绕过苹…

MSPM0L1306——定时器

相关配置: #include "ti_msp_dl_config.h"int main(void) {SYSCFG_DL_init();//清除定时器中断标志NVIC_ClearPendingIRQ(TIMER_0_INST_INT_IRQN);//使能定时器中断NVIC_EnableIRQ(TIMER_0_INST_INT_IRQN);while (1) { } }//定时器…

Thinkpad系列产品进入Bios并设置U盘启动

Thinkpad系列产品,进入Bios并设置U盘启动,常用于以下场景: 1. 安装操作系统。 通过U盘启动盘,用户可以在电脑无法从硬盘启动或需要重装系统时,将操作系统安装到电脑中。这种方法简单且有效,节省了时间并方便…

Redis-数据结构-跳表详解

Redis概述 Redis-数据结构-跳表详解 跳表(Skip List)是一种基于并联的链表结构,用于在有序元素序列中快速查找元素的数据结构。 Redis 中广泛使用跳表来实现有序集合(Sorted Set)这一数据结构。 1.跳表的基本概念和…

1832javaERP管理系统之实践教学管理Myeclipse开发mysql数据库servlet结构java编程计算机网页项目

一、源码特点 java erp管理系统之实践教学管理是一套完善的web设计系统,对理解JSP java编程开发语言有帮助采用了servlet设计,系统具有完整的源代码和数据库,系统采用web模式,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Mye…

早期发现,健康生活!第三届ZAODX世界肿瘤早筛大会圆满落幕!

2024年6月15日-16日,第三届ZAODX世界肿瘤早筛大会在雄安新区盛大开幕!本次会议由河北雄安新区管理委员会公共服务局指导,第三届ZAODX世界肿瘤早筛大会组委会和早筛网主办,粤港澳大湾区精准医学研究院(广州)…

双绞线(网线)的制作与测试

实验目的 1、熟悉常用双绞线(网线)及其制作工具的使用; 2、掌握非屏蔽双绞线的直通线、交叉线的制作及连接方法; 3、掌握双绞线连通性的测试。 设备要求:RJ45压线钳,RJ45水晶头,UTP线缆&…

《跟我一起学“网络安全”》——安全设备

安全设备 一、安全设备–IDS IDS入侵检测 (1)什么是入侵检测: 入侵检测系统(intrusion detection system,简称“IDS”)是一种对网络传输进行即时监视,在发现可疑传输时发出警报或者采取主动反应措施的网络安全设备。…