这几天看到几篇关于尾递归的文章,之前对尾递归没有多大概念,所以回头研究了一下尾递归。

尾递归的概念

尾递归(Tail Recursion)的概念是递归概念的一个子集。对于普通的递归,由于必须要记住递归的调用堆栈,由此产生的耗用是难以估量的。比如下文中php小节第一个例子使用php写一个阶乘函数,就是由于递归造成了栈溢出的错误。尾递归出现的目的就是消除递归栈耗损这个缺憾的。

从代码层面看,尾递归其实一句话就可以说清楚了:

函数的最后一个操作是递归调用

比如"菲波纳锲"数列的php的递归实现:

这是递归函数,但不是尾递归,因为fibonacci的最后一个操作是加法操作。

转化为尾递归:

fibonacci2就是一个尾递归,它增加两个累加器acc1和acc2,并给出初始的值。记住:递归转化为尾递归的思想一定是增加累加器,减少递归外操作。

尾递归在不同语言上的应用也是不同的。最常使用的就是函数式编程Erlang,几乎是所有出现递归的函数全部都修改成为尾递归。下面说一下尾递归在几个不同的语言上的表现和应用。

php中的尾递归

我们做个实验

普通递归:

尾递归:

实验结果:

事实证明,

尾递归在php中是没有任何优化效果的!

在php中尾递归正如老王(http://huoding.com/2012/06/25/158)文章里面说的,并没有任何优化,但是却可以使用Trampoline概念来消除递归,这里也不说了

C中的尾递归

在C中的尾递归优化是gcc编译器做的。在gcc编译的时候加上-O2会对尾递归进行优化

我们可以直接看生成的汇编代码:

(使用gdb, gcc –O2 factorial.c –o factorial;    disass factorial)

未加-O2生成的汇编:

加了O2优化的汇编:

不要头大,我也是初看汇编,但是这份代码非常简单,去网上稍微搜搜命令,大致就能理解:

gcc做的确实是智能优化。

如果你还有兴趣,你可以使用-O3对尾递归进行优化,并查看其中的汇编指令

-O3的优化是直接将循环展开

总结

一般的线性递归修改成为尾递归最大的优势在于减少了递归调用栈的开销。从php那个例子就明显看出来递归开销对程序的影响。但是并不是所有语言都支持尾递归的,即使支持尾递归的语言也一般是在编译阶段对尾递归进行优化,比如上例中的C语言对尾递归的优化。在使用尾递归对代码进行优化的时候,必须先了解这门语言对尾递归的支持。

推荐几篇文章

php和lua尾递归:

C的尾递归分析:

golang的尾递归讨论:

本文转自轩脉刃博客园博客,原文链接:http://www.cnblogs.com/yjf512/archive/2012/07/12/2588481.html,如需转载请自行联系原作者

php 尾递归,又见尾递归相关推荐

  1. [算法]递归(尾递归和非尾递归)

    尾递归,性能高,与迭代一致: 非尾递归,性能低,将其转为迭代(注重:出栈压栈操作)以提高性能. ref1. 递归算法转换为非递归算法的技巧 2017-11-22 算法与数学之美 https://mp. ...

  2. 斐波那契尾递归函数java_尾递归实现斐波那契数列

    一.斐波那契数列 斐波那契数列指的是这样一个数列 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6 ...

  3. php 尾递归,关于尾递归的使用详解

    这几天看到几篇关于尾递归的文章,之前对尾递归没有多大概念,所以回头研究了一下尾递归. 尾递归的概念 尾递归(Tail Recursion)的概念是递归概念的一个子集.对于普通的递归,由于必须要记住递归 ...

  4. 通俗易懂----尾递归

    差距在这: 线性递归:计算到头之后还要再回溯一遍 (相当于运算了两遍) 尾递归 :计算到头就得到结果,不回溯  (就运算一遍) 看代码,简单求阶乘公式: 线性递归: // Line recursion ...

  5. 利用尾递归减少栈空间的消耗

          首先,需要给出一个定义,什么是尾递归.在<算法精解>中给出的定义如下:       如果一个函数中所有递归形式的调用都出现在函数的末尾,我们称这个递归函数是尾递归的.当递归调用 ...

  6. JavaScript, ABAP和Scala里的尾递归(Tail Recursion)

    这是Jerry 2021年的第 12 篇文章,也是汪子熙公众号总共第 283 篇原创文章. 今天是2021年1月20日,看看历史上的今天都发生了什么. 2004年1月20日,第一个公开版本的Scala ...

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

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

  8. python 函数式编程尾递归优化 day16

    函数编程的特征: 1不可变:不用变量保存状态,不修改变量 #非函数式 a = 1 def incr_test1():global a#一旦更改全局变量后后面再调用a就容易乱a += 1return a ...

  9. Python 算法之递归与尾递归,斐波那契数列以及汉诺塔的实现

    文章目录 递归概念 递归要素 递归与迭代的区别 示例一:阶乘 示例二:斐波那契数列 示例三:汉诺塔问题 尾递归 Python 中尾递归的解决方案 递归概念 递归:程序调用自身的编程技巧称为递归( re ...

最新文章

  1. Java 24岁!Google加持的Kotlin真能取代它?
  2. nyoj------203三国志
  3. 关于从 coding 拉项目的操作
  4. Linux硬链接 软链接
  5. [crypto]-05-转载:PKCS #1 RSA Encryption Version 1.5介绍
  6. 58同城数据库架构最佳实践
  7. html基于web2.0标准,晕倒:“用web2.0来制作符合标准的页面”
  8. HGE2D引擎按键消息分析
  9. python屏幕文字识别_学会python就是如此任性,15行代码搞定图片文字识别,附源码...
  10. Kaggle 年度报告出炉:数据科学家年轻高学历,薪资近百万
  11. mysql6.0_MySQL6.0安装
  12. Computer Browser服务自动停止
  13. Biopython SeqIO 读取序列文件,读取信息,写入序列
  14. type=file 把默认的未选择文件换成别的_PS文件的新建、存储与格式
  15. 互联网名词和广告名词缩写大全
  16. office VBA开发视频教程
  17. 公交线路图-数据结构课程设计C++实现
  18. IIS 环境下 PHP无法显示错误信息------500错误
  19. 影响应用商城搜索排名的因素
  20. 中国风网站建设设计的2大要素

热门文章

  1. 咖说丨清华姚班/智班2020级新生来了!中国奥数新晋“一姐”在列
  2. Arjian不是Arjan:樱桃司这八年
  3. 点击链接加入群【Java魔方家园】:http://jq.qq.com/?_wv=1027k=Z6x
  4. Python : UnicodeEncodeError: 'gbk' codec can't encode character '\u200b' in position
  5. 三层交换与路由器之间连接配置
  6. 计算机应用及动画制作教材,中央电大 flash动画制作
  7. OKHttp请求访问-同步-JSON-添加请求头参数
  8. 双线机房和双线双IP机房的区别
  9. Android 多线程读写文件
  10. 2022年RPA将从IT领域继续扩展至非IT领域,非IT领域5大场景RPA应用