java递归简单例子_开发常用算法之递归算法的深入分析

刀枪终入库,老马牧南山,喝杯清茶,说点故事,和你聊一聊编程这件事,我是南山,一个普通的程序员,一个喜欢简单,坚持自己的肥仔……

0ed2380a960fd54585b785ebf45055d1.png

递归是工作中经常会使用到的一种算法,比如阶乘的计算就是利用递归来实现的,如果您还没有接触编程方面的内容,要理解递归其实并不困难,它就是在一个函数的内部调用了本身,执行的情况特别类似是一个循环,如果要这么说递归似乎没有什么好说的,但是在这里我希望和大家讨论的是递归这种算法在使用的时候对系统性能的影响,同时也会和大家分析下在递归函数执行过程中内存的变化情况。

特别提醒,在下述内容中方法和函数是同一个意思。

递归的实现

为了让大家更好的理解接下来介绍的内容,同时也为了照顾那些并没有了解过递归的读者,这里我们先来为搭建演示下在 Java 中到底如何通过递归来实现阶乘计算的:

cab81a5013c383d11803fbb673621ece.png

对于上述这段代码来说,开发人员并不陌生,这也是阶乘最简单的例子,大家可以看到在阶乘运算函数 factorial() 中,如果传入的参数大于1的话,就会进行一次乘法运算,通过断点调试理解这个过程并不困难,但是在这里想和大家讨论的是在这个阶乘运算过程中,系统的内存是如何变化的呢?在上一篇文章中和大家提到过,在系统运行过程中函数参数以及其中的变量都会存放在栈中,那么像这种重复调用自己的函数它的栈是如何变化的呢?通过研究这种变化,就可以知道这种算法在工作中对系统的性能有多大的影响,这是一个值得所有开发人员思考的问题。

递归的分析

要研究清楚刚才的问题,我们必须先清楚在程序运行过程中,如果一个函数调用了另外一个函数,那么接下来会发生怎样的情况?这里设置了这样一段代码,就是当数值小于 10 的时候,加上1输出,如果大于 10 的话,需要先减去 10 ,再加上 1输出(当然,这段代码没有任何作用,纯粹是为了制造一个这样的场景),在Java 中可以用如下的方法实现:

7915fd195a47b5260bdee9b4d21c8022.png

我们可以看到,在这段代码中,add中调用了另外一个方法 sub,但是这时候add 方法并没有结束,所以在程序中应该存在两个栈,分别是存储sub、add 两个方法中内容的,也就是如下情况:

8348be61f3aa806904bbb13f409986bf.png

为什么 sub 对应的栈会在 add 上边呢?这是因为 栈 是后进先出的,因为sub方法在 add 方法之后执行,所以 sub 对应的 栈应该在 add 上边,当sub 方法执行完毕之后,系统自动销毁这块空间,重新又回到了 add 方法中,最后当程序结束的时候 add 方法对应的空间也会被销毁,其中的变量、参数也会随着被消失,为了方便大家理解这个过程,这里准备了一张过程图:

5e361fd61c5715aa82dac5ed79bdde8e.png

到这里为止,我们知道了在一个函数中运行另外一个函数,会在内存中为这个函数开辟一块空间,当这个函数执行完毕之后,这块空间会被计算机销毁,重新回到之前的函数中,也就是说在此之前,运行的这个函数占据的空间一直存在,明白这个道理之后,我们再次回到刚开始的递归算法中。假设我们现在要计算 3 的阶乘,那么在整个过程中,内存的变化就可以这样表示:

d405dbc67ddddc1a6e3c5269a8054c40.png

很显然,随着我们传入的参数越来越大,整个过程会越来越复杂,而每次调用递归函数调用自身之后,都会在计算机中开辟一块新的空间,这说明使用此种方法对系统的性能会有一定的影响,特别是当我们递归执行的次数很多的时候,特别容易造成系统崩溃。

好的,到这里为止,关于递归算法的使用到这里就为大家介绍完了,不知道您是否掌握了呢?当然上述内容是我结合自身的工作经验以及一些资料整理出来的,其中可能有些地方存在问题,敬请批评指正,欢迎您留下自己的看法,另外如果感觉这些内容对您的工作或者学习有所帮助的话,请分享给您周围的朋友或者同事,也欢迎您点赞、关注,我将持续更新更多编程方面的内容,感谢您的支持!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值