首页 > 其他分享 >函数递归(小知识)

函数递归(小知识)

时间:2024-10-28 09:45:55浏览次数:7  
标签:函数 递归 代码 知识 问题 阶乘 迭代 Fact

1.递归是什么

         递归是学习C语言无法绕开的一个问题,那我们就会产生问题,什么是递归?递归的作用是什么?递归可在给我们编写程序时提供什么便利?

         递归其实就是解决问题的一种方法,在C语言中,递归就是函数自己调用自己

举例一个最简单的的递归代码:

上述代码只是为了做一个示例,为了演示递归的基本形式,并不是为了解决实际的问题,代码最终会陷入死循环,从而导致栈溢出(Stack overflow)

1.1 递归的思想

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

通俗的理解就是,递归中的递是递推的意思,归就是回归的意思,接下来慢慢体会。

该图出自于A_caim_rhino。便于诸君理解。

 1.2递归的限制条件

 递归在书写的时候,有连个必要的条件:

一,递归存在限制条件,当满足这个限制条件的时候,递归便不再继续。

二,每次递归调用之后越来越接近这个条件。

2.递归举例

2.1举例1:求n的阶乘

 2.1.1分析和代码的实现

n的阶乘公式:n! = n *(n - 1)!

例如:5! = 5 * 4 * 3 * 2 * 1

           4! = 4 * 3 * 2 * 1

所以:5! = 5 * 4!

从这个公式不难看出:如何把一个较大的问题,转换为一个与原问题相似,但规模较小的问题来求解的。

n的阶乘和n - 1的阶乘是1相类似的问题,但是规模上要少了n。但是有一种特殊的情况是:当       n == 0的阶乘是1,而其余n的阶乘都是可以通过上面的公式计算。

这样就能写出n的阶乘的递归公式如下:

 那我们就可以写出Fact求n的阶乘,假设Fact(n)就是求n的阶乘,那么Fact(n-1)就是求n-1的阶乘,函数如下:

 

 

2.1.2 画图推演 

 

基于上述的讲解,我想诸君对递归已经有了一个比较清晰的理解。 

3.递归与迭代

 递归是一种很好的编程技巧,但是和很多技巧一样,也有可能被误用的,就像举例1一样,看到

 推导的公式,很容易就会被写成递归的形式:

 

 

 

 

 

 

 

Fact函数是可以产生正确的结果,但是在递归函数调用的过程中涉及一些运行时的开销。 

 

 所以如果不想使用递归,就得想其他的办法,通常就是迭代的方式(通常就是循环的方式)。

比如:计算n的阶乘,也是可以产生1~n的数字累积乘在一起。

 

 上述代码是能够完成任务,并且效率是比递归的方式更好的。

事实上,我们看到的许多问题是以递归的形式进行解释的,这只是因为它比非递归形式更加的清晰,但是这些问题的迭代实现往往比递归形式实现效率更高。

当一个问题非常复杂,难以使用迭代的方式实现时,此时递归的简洁性便可以补偿它所带来的运行时的开销。

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

我们举出更加极端的例子,就像计算出第n个斐波那契数,是不适合使用递归求解的,但是斐波那契数的问题通过使用递归的形式描述,如下:

我们将代码写成递归的形式,如下所示:

 

 

当我们n如果输入更大的数字时,比如50,60等等,需要很长的时间才能得出结果, 这个计算所花费的时间,是我们很难接受的,这也说明了递归的写法是非常低效的,那是为什么呢?

 其实递归程序会不断展开,在展开的过程中,我们很容易发现,在递归的过程中计算,会有重复的计算,而且递归层次越深,冗余的计算就会越多。

 所以我们就需要用到迭代的方式进行计算。

 迭代的方式去实现这个代码,效率就要高出很多了。但也要适可而止,而不是什么问题都要用迭代的方式去解决。

小结

递归与迭代的探究还需诸君亲身共性,需得实践出真知,如果诸君喜欢这篇blog,还请点点赞,转转发,本人定铭感五内。谢谢大家

标签:函数,递归,代码,知识,问题,阶乘,迭代,Fact
From: https://blog.csdn.net/2401_87194328/article/details/143279244

相关文章

  • JavaWeb知识点总结 我的学习笔记
    JavaWeb我的学习笔记一、动态网页开发1.动态网页2.系统架构C/S架构B/S架构B/S与C/S的比较3.URL通信三要素4.Tomcat服务器二、Servlet1.Servlet简介2.Servlet快速入门入门样例执行原理3.Servlet的体系结构4.servlet的十大方法5.Servlet生命周期6.在web.xml中配置servl......
  • GaussDB数据库SQL系列-自定义函数
    一、前言华为云GaussDB数据库是一款高性能、高安全性的云原生数据库,在GaussDB中,自定义函数是一个不容忽视的重要功能。本文将简单介绍一下自定义函数在GaussDB中的使用场景、使用优缺点、示例及示例解析等,为读者提供指导与帮助。二、自定义函数(Function)概述在SQL中,自定义函数(Fu......
  • CodeQL学习笔记(2)-QL语法(递归)
    最近在学习CodeQL,对于CodeQL就不介绍了,目前网上一搜一大把。本系列是学习CodeQL的个人学习笔记,根据个人知识库笔记修改整理而来的,分享出来共同学习。个人觉得QL的语法比较反人类,至少与目前主流的这些OOP语言相比,还是有一定难度的。与现在网上的大多数所谓CodeQL教程不同,本系列基于......
  • 2.哈希函数
    哈希函数目标:极快且稳定特点:确定性/幂等性:对于相同的输入,哈希算法应始终产生相同的输出。这样才能确保哈希表是可靠的。效率高:计算哈希值的过程应该足够快,哈希表的实用性越高。均匀分布:哈希算法应使得键值对均匀分布在哈希表中。分布越均匀,哈希冲突的概率就越低......
  • 【C/C++】2.函数传入复杂类型实例时,传入值参数和引用参数的区别
    1.值参数传递(PassbyValue)原理:传入参数时会拷贝一份对象副本。优点:副本在函数内部可随意修改,不会影响原始数据。缺点:对于复杂类型,拷贝对象会消耗更多内存和性能。适用场景:函数只需读取少量数据,且无需修改原对象时,可以考虑值传递。voidprocessData(MyClassobj){......
  • 高效协作,智慧共享:精选十款客服知识库
    在当今这个快速变化且高度竞争的商业环境中,优质的客户服务已经成为企业成功的关键因素之一。而一个高效、智能的客服知识库不仅能够提升客服团队的工作效率,还能确保客户问题得到快速、准确的解决,从而增强客户满意度和忠诚度。本文将精选十款客服知识库工具,它们通过高效协作......
  • java函数式编程
    目录Lambda表达式Lamabda表达式语法语法重要特征代码示例Lambda表达式引用方法Lambda表达式创建线程Lambda表达式中的闭包问题常用的函数式接口Consumer接口的使用Predicate接口的使用Comparator接口的使用Stream流Stream流的生成方式常用方法数据过滤数量限制......
  • YOLOv8改进 | Conv篇 | 2024最新Kolmogorov-Arnold网络架构下的KANConv(包含九种不同类
    一、本文介绍本文给大家带来的改进机制是2024最新的,Kolmogorov-Arnold网络(ConvolutionalKANs),这种架构旨在将Kolmogorov-Arnold网络(KANs)的非线性激活函数整合到卷积层中,从而替代传统卷积神经网络(CNNs)的线性变换。与标准的卷积神经网络(CNN)相比,KANConv层引入了更多的参数,因......
  • CAD知识点概览 CAD数据交换与二次开发
    CAD知识点概览章节目录一、CAD基础概念与应用领域二、CAD软件界面与基本操作三、二维绘图与编辑四、尺寸标注与文字标注五、三维建模与编辑六、视图显示控制与打印输出七、图层管理与数据库管理八、CAD数据交换与二次开发九、CAD学习方法与资源推荐一、CAD基础概念与应用......
  • ts 构造函数类型和构造函数返回值类型的区别
    在TypeScript中,构造函数类型和构造函数返回值类型是两个不同的概念,它们分别用于描述构造函数的行为和结果。下面详细解释这两者的区别。1.构造函数类型构造函数类型描述的是一个类的构造函数的签名,包括构造函数的参数类型和返回类型。它定义了如何通过new关键字创建一个实......