简单来说,递归即是调用自己本身。所有递归都应该有至少一个基本条件,在满足基本条件时不进行递归。

给出一个递归实例:

 int fact(int N){
if(N==1)
return 1;
else
return N*fact(N-1);
}

每一个递归方法的执行都分为前进和回退两个阶段,上例中计算5的阶乘,前进阶段得到的结果是:

(5*(4*(3*(2*(1)))))

回退阶段则由内向外,依次计算括号中的值。

应用到程序中,分别对应压栈和出栈。考虑到这种做法,每次调用都会压栈出栈,效率很低。除此之外,每次递归创建新的栈在递归深度过深的时候,会引起栈溢出,也就是可以分给创建栈的内存不足的情况。尾递归的方法由此提出。

尾递归,简单来说,就是将递归语句写到最后一行且不参与任何计算。本质上,每次递归将接受上一次递归的传参,并将本次计算结果传给下一次递归,当递归到达终结条件的时候,其计算值即为返回值。这样相比普通递归,省去了递归的回退过程,也即不用再回退到上一次递归作运算,自然就省去了很多创建栈、压栈与出栈的工作,性能得到提升。将上例改写为尾递归为:

 int fact(int N){
if(N==1)
return 1;
else
return fact(N-1,N);
} int fact(int N, int M){
if(N==1)
return M;
else
return fact(N-1, N*M);
}

这是有外及里的尾递归,当计算斐波那契数列的时候就要换一种思路,即由里及外。

斐波那契问题描述:每个兔子出生后的第三个月后,每个月都可以生下一对兔子,如果不考虑兔子死亡问题,第一个月有新出生的一对兔子,那第N个月有多少兔子?

其尾递归代码如下:

 int Fibonacci(int N, int first, int second, int begin){
if(begin>=N)
return first;
else
return Fibonacci(N, second, first+second, begin+1);
}

但这要求编译器能对尾递归进行优化,每次重用或者说覆盖原来递归方法的栈,而不是新建栈。遗憾的是JAVA和python都不支持尾递归的优化,JAVA的尾递归代码与普通递归无异。可能JVM是想在出现异常时更好地输出堆栈信息的缘故。所以,JAVA中一般能用迭代就不用递归。

尾递归和JAVA的更多相关文章

  1. 尾递归(java)

    一般递归: 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多 ...

  2. Spark案例分析

    一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...

  3. 【Java】斐波那契数列(Fibonacci Sequence、兔子数列)的3种计算方法(递归实现、递归值缓存实现、循环实现、尾递归实现)

    斐波那契数列:0.1.1.2.3.5.8.13………… 他的规律是,第一项是0,第二项是1,第三项开始(含第三项)等于前两项之和. > 递归实现 看到这个规则,第一个想起当然是递归算法去实现了, ...

  4. 在Java中谈尾递归--尾递归和垃圾回收的比较(转载)

    我不是故意在JAVA中谈尾递归的,因为在JAVA中谈尾递归真的是要绕好几个弯,只是我确实只有JAVA学得比较好,虽然确实C是在学校学过还考了90+,真学得没自学的JAVA好 不过也是因为要绕几个弯,所 ...

  5. Java中谈尾递归--尾递归和垃圾回收的比较

    一.首先我们讲讲递归 1.递归的本质是,某个方法中调用了自身,本质还是调用了一个方法,只是这个方法正好是自身而已 2.递归因为是在自身中调用自身,所以会带来以下三个显著特点:    1.调用的是同一个 ...

  6. 在Java中谈尾递归--尾递归和垃圾回收的比较

    我不是故意在JAVA中谈尾递归的,因为在JAVA中谈尾递归真的是要绕好几个弯,只是我确实只有JAVA学得比较好,虽然确实C是在学校学过还考了90+,真学得没自学的JAVA好 不过也是因为要绕几个弯,所 ...

  7. Java8函数之旅 (六) -- 使用lambda实现Java的尾递归

    前言 本篇介绍的不是什么新知识,而是对前面讲解的一些知识的综合运用.众所周知,递归是解决复杂问题的一个很有效的方式,也是函数式语言的核心,在一些函数式语言中,是没有迭代与while这种概念的,因为此类 ...

  8. [Java 8] (8) Lambda表达式对递归的优化(上) - 使用尾递归 .

    递归优化 很多算法都依赖于递归,典型的比如分治法(Divide-and-Conquer).但是普通的递归算法在处理规模较大的问题时,常常会出现StackOverflowError.处理这个问题,我们可 ...

  9. Java 递归、尾递归、非递归、栈 处理 三角数问题

    import java.io.BufferedReader; import java.io.InputStreamReader; //1,3,6,10,15...n 三角数 /* * # 1 * ## ...

随机推荐

  1. jupyter notebook 中同时添加Python2和3,在conda下配置R语言运行的环境

    1.第一步,安装Python2的环境 首先,在安装anaconda的时候先选择一个Python安装,我先安装的是Python3 然后,在anaconda Prompt下创建Python2环境 现在,还 ...

  2. DNN训练技巧(Tips for Training DNN)

    本博客是针对李宏毅教授在Youtube上上传的课程视频<ML Lecture 9-1:Tips for Training DNN>的学习笔记. 课程链接 Recipe of Deep Le ...

  3. linux execl()函数 关于execl()函数族的用法不在赘述,

    linux execl()函数 关于execl()函数族的用法不在赘述, linux 网络编程 1---(基本概念) 1.TCP和UDP协议 共同点:同为传输层协议 不同点: TCP:有连接,可靠 U ...

  4. C 实战练习题目2

    题目:企业发放的奖金根据利润提成. 利润(I)低于或等于10万元时,奖金可提10%: 利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可提成7.5%: 20万到4 ...

  5. C++ STL 常用容器之 stack

    C++ STL Container--Stack 栈是一种先进后出(LIFO)的数据结构,限制只能在一端完成插入和删除操作,这一端叫做栈顶(top),另一端即为栈底(bottom).C++ STL(S ...

  6. Hbase 整合 Hadoop 的数据迁移

    上篇文章说了 Hbase 的基础架构,都是比较理论的知识,最近我也一直在搞 Hbase 的数据迁移, 今天就来一篇实战型的,把最近一段时间的 Hbase 整合 Hadoop 的基础知识在梳理一遍,毕竟 ...

  7. Redis调用lua生成验证码

    场景: ​ 通过微信公众号拿验证码在APP上绑定,为了防止重复,尝试使用reids-lua的方法实现此功能 以下是 php 调用 redis.eval 方法传入的 lua 方法,当然这只是修改后的,保 ...

  8. gunicorn的作用

    gunicorn是什么: gunicorn是一种unix上被广泛使用的Python WSGI UNIX HTTP Server WSGI是什么: 先说下 WSGI 的表面意思,Web Server G ...

  9. UITextFiled-集合目录

    键盘弹起遮挡输入输入框(UITextFiled或者UITextView)                   对于键盘弹起遮挡输入框的问题以前也想过解决办法比如:监听系统键盘弹出通知.根据每个控件所在 ...

  10. Aircoinst 三层架构ASP.NET开源

    <注意! 本源码为我本人所写,可能有点烂.仅供学习使用,请勿进行商业用途~!> <本源码永久归于MineLSG 及 Aircoinst_慈 所拥有> 使用方法:直接拷贝 一.结 ...