2.2基本算法之递归和自调用函数_你为什么学不会递归?读完这篇文章轻松理解递归算法...
对于很多编程初学者来说,递归算法是学习语言的最大障碍之一。很多人也是半懂不懂,结果学到很深的境地也会因为自己基础不好,导致发展太慢。
可能也有一大部分人知道递归,也能看的懂递归,但在实际做题过程中,却不知道怎么使用。今天,我们就来说一说递归算法的使用。
什么是递归
递归,在数学与计算机科学中,是指在函数的定义中使用函数自身的方法。也就是说,递归算法是一种直接或者间接调用自身函数或者方法的算法。
通俗来说,递归算法的实质是把问题分解成规模缩小的同类问题的子问题,然后递归调用方法来表示问题的解。
递归的基本原理
第一:每一级的函数调用都有自己的变量。
第二:每一次函数调用都会有一次返回。
第三:递归函数中,位于递归调用前的语句和各级被调用函数具有相同的执行顺序。
第四:递归函数中,位于递归调用后的语句的执行顺序和各个被调用函数的顺序相反。
第五:虽然每一级递归都有自己的变量,但是函数代码并不会得到复制。
递归的优缺点
优点 |
缺点 |
●实现简单 ●可读性好 |
●递归调用,占用空间大 ●递归太深,易发生栈溢出 ●可能存在重复计算 |
递归的三大要素
第一要素:明确你这个函数想要干什么。先不管函数里面的代码什么,而是要先明白,你这个函数的功能是什么,要完成什么样的一件事。
第二要素:寻找递归结束条件。我们需要找出当参数为啥时,递归结束,之后直接把结果返回,请注意,这个时候我们必须能根据这个参数的值,能够直接知道函数的结果是什么。
第三要素:找出函数的等价关系式。我们要不断缩小参数的范围,缩小之后,我们可以通过一些辅助的变量或者操作,使原函数的结果不变。
递归的过程
具体地说,如果递归函数调用自己,则被调用的函数也将调用自己,这将无限循环下去,除非代码中包含终止调用链的内容。通常的方法将递归调用放在if语句中。例如,void类型的递归函数recurs()的代码如下:
用文字再现这段代码块的内容:
只要if语句为true,每个recurs()调用都将执行statement1,然后再调用recurs(),而不会执行statements2 。当前调用结束后,程序控制权将返回给调用它的recurs(),而该recurs()将执行其statements2部分,然后结束,并将控制权返回给前一个调用,依次类推。
递归的使用
递归的强大之处在于它允许用户用有限的语句描述无限的对象。因此,在计算机科学中,递归可以被用来描述无限步的运算,尽管描述运算的程序是有限的。 这一点是循环不太容易做到的。
编写正确的递归算法,一定要有 ”归“ 的步骤,也就是说递归算法,在分解问题到不能再分解的步骤时,要让递归有退出的条件,否则就会陷入死循环,最终导致内存不足引发栈溢出异常。
下面,我们通过两个例子来学习一下,递归的使用:
例一:递归求阶乘
例二:递归求斐波那契数列
从上面的步骤我们可以清晰的看到递归算法的第一步是分治,把复杂的大的问题,给拆分成一个一个小问题,直到不能再拆解,通过退出条件retrun,然后再从最小的问题开始解决,只到所有的子问题解决完毕,那么最终的大问题就迎刃而解。
递归的优化方法
递归问题中想到思路本身不非常难,真正的难点在于如何优化。
1、考虑是否重复计算
如果你使用递归的时候不进行优化,是有非常非常非常多的子问题被重复计算的。因此,使用递归的时候,必要须要考虑有没有重复计算,如果重复计算了,一定要把计算过的状态保存起来。
2、考虑尾递归
对于递归的问题,我们一般都是从上往下递归的,直到递归到最底,再一层一层着把值返回。
不过,有时候当 n 比较大的时候,例如当 n = 10000 时,那么必须要往下递归10000层直到 n <=1 才将结果慢慢返回,如果n太大的话,可能栈空间会不够用。这个时候,就可以用尾递归优化来解决。
顾名思义,尾递归就是从最后开始计算, 每递归一次就算出相应的结果, 也就是说, 函数调用出现在调用者函数的尾部, 因为是尾部, 所以根本没有必要去保存任何局部变量。直接让被调用的函数返回时越过调用者, 返回到调用者的调用者去。
有的人刚接触算法的时候,一直都惧怕递归,也很少或者说几乎就不写递归的代码。但其实学习了以后,发现递归还是挺可爱的。就像在数学找一组数字的规律一样,可以锻炼我们的思维。希望这篇文章,能额昂你有所收获。
相关链接:
几种快速优化MongoDB的方法,从此优化不再难!
4种网页设计技巧:图文搭配,网页不累!
巧用这10条MySQL技巧,事半功倍!
学会这8个Mybatis使用技巧,让你省去没必要的麻烦
点击文末“”咨询,免费来云和试听课程——UI视觉交互全科班、Python人工智能高薪班、JAVA大数据企业直通班、HTML5全栈精英班、Unity虚拟现实大师班,座位有限,先抢先得!
2.2基本算法之递归和自调用函数_你为什么学不会递归?读完这篇文章轻松理解递归算法...相关推荐
- 可能存在无限递归_你为什么学不会递归?读完这篇文章轻松理解递归算法
对于很多编程初学者来说,递归算法是学习语言的最大障碍之一.很多人也是半懂不懂,结果学到很深的境地也会因为自己基础不好,导致发展太慢. 可能也有一大部分人知道递归,也能看的懂递归,但在实际做题过程中,却 ...
- 2.2基本算法之递归和自调用函数_一文学会递归解题
前言 递归是算法中一种非常重要的思想,应用也很广,小到阶乘,再在工作中用到的比如统计文件夹大小,大到 Google 的 PageRank 算法都能看到,也是面试官很喜欢的考点 最近看了不少递归的文章, ...
- 2.2基本算法之递归和自调用函数_用栈算法递归解决汉诺塔问题
今天博主收一下线性表的尾,最近我们要学习的内容是栈和队列板块,栈和队列板块分为两讲,第一讲也就是今天我们主要学习栈的相关知识,包括栈的定义.栈的顺序表示及实现,栈的链式表示,栈的应用举例,以及栈递归实 ...
- 2.2基本算法之递归和自调用函数_数据结构与算法之5——队列和栈
栈和队列比较简单,而且实用性非常广泛,这里主要介绍一下他们的概念和实现,在很多算法中,栈和队列的运用很重要,因此,虽然简单确是最重要的数据结构之一,必须重视. 栈是保证元素后进先出(后存入者先使用,L ...
- 2.2 基本算法之递归和自调用函数 1751 分解因数 python
http://noi.openjudge.cn/ch0202/1751/ """ 2.2 基本算法之递归和自调用函数 1751 分解因数 http://noi.openj ...
- 2.2 基本算法之递归和自调用函数 8758 2的幂次方表示 python
http://noi.openjudge.cn/ch0202/8758/ """ 2.2 基本算法之递归和自调用函数 8758 2的幂次方表示 python http:/ ...
- 2.2基本算法之递归和自调用函数_7592 求最大公约数问题
http://noi.openjudge.cn/ch0202/7592/ /* 2.2基本算法之递归和自调用函数_7592 求最大公约数问题 http://noi.openjudge.cn/ch020 ...
- 【完结】深度学习CV算法工程师从入门到初级面试有多远,大概是25篇文章的距离...
文/编辑 | 言有三 转载自言有三 一直有同学希望我在公众号写写面试相关的东西,一直没写.我们不会开相关的板块,因为没有标准,容易引起争议,而且可能会加重大家的浮躁和焦虑. 不过关于面试,有三还是有一 ...
- NOI题库答案 2.2基本算法之递归和自调用函数
1696:逆波兰表达式 总时间限制: 1000ms 内存限制: 65536kB 描述 逆波兰表达式是一种把运算符前置的算术表达式,例如普通的表达式2 + 3的逆波兰表示法为+ 2 3.逆波兰表达式的优 ...
最新文章
- 打造自己的树莓派监控系统3--canvas.js绘制数据
- php获取页面的可视内容高度,网页制作技巧:获取页面可视区域的高度_css
- P3835 【模板】可持久化平衡树
- 渐进式web应用程序_如何在渐进式Web应用程序中添加到主屏幕
- snmp获取交换机日志_日志审计系统和数据库审计系统的区别
- C++ Primer 第五版 第7章类 7.1——类讲解(成员函数、非成员函数、构造函数)
- ORA-02266错误处理
- java实体类中有枚举类型_实体类的枚举属性--原来支持枚举类型这么简单,没有EF5.0也可以...
- Java 8 Comparator: 列表排序
- DXperience12.2入门设置以及应用教程
- STC15单片机实战项目 - 原理图设计
- Win11键盘锁住怎么恢复?
- OSChina 周四乱弹 —— 我看你TM像病毒
- Modelica示例——比较器电路
- test_and_set_bit
- mysql获取当天每小时统计_详解mysql 获取某个时间段每一天、每一个小时的统计数据...
- Android 音频架构
- 取消Rainbow Brackets彩色框
- 关闭notepad++自动更新提示,关闭烦人的an update is available, do you want to download it?
- 【材料课堂】材料科学基础108个重要知识点!(建议收藏)
热门文章
- Tether销毁5亿USDT;BCH将于11月15日硬分叉,SV-Pool已向普通矿工开放
- JML规格编程——BUAA OO第三单元作业总结
- Spring Boot定时任务应用实践
- [TJOI2016][HEOI2016]排序
- Ubuntu .deb包安装方法
- Attempted to access a cursor after it has been clo
- 如何很好的使用Linq的Distinct方法
- 使用Python的库qrcode生成二维码
- 5个找出Linux中“二进制命令”描述和系统中位置的方法
- [ linq2db ] 使用LoadWith()对外键进行查询