尾递归和一般的递归不同在对内存的占用,普通递归创建stack累积而后计算收缩,尾递归只会占用恒量的内存(和迭代一样)。SICP中描述了一个内存占用曲线,用以上答案中的Python代码为例(普通递归):

def recsum(x):
if x == 1:
return x
else:
return x + recsum(x - 1)

当调用recsum(5),Python调试器中发生如下状况:

recsum(5)
5 + recsum(4)
5 + (4 + recsum(3))
5 + (4 + (3 + recsum(2)))
5 + (4 + (3 + (2 + recsum(1))))
5 + (4 + (3 + (2 + 1)))
5 + (4 + (3 + 3))
5 + (4 + 6)
5 + 10
15

这个曲线就代表内存占用大小的峰值,从左到右,达到顶峰,再从右到左收缩。而我们通常不希望这样的事情发生,所以使用迭代,只占据常量stack space(更新这个栈!而非扩展他)。
---------------------
(一个替代方案:迭代
for i in range(6):
sum += i
因为Python,Java,Pascal等等无法在语言中实现尾递归优化(Tail Call Optimization, TCO),所以采用了for, while, goto等特殊结构代替recursive的表述。Scheme则不需要这样曲折地表达,一旦写成尾递归形式,就可以进行尾递归优化。
---------------------
Python中可以写(尾递归):
def tailrecsum(x, running_total=0):
if x == 0:
return running_total
else:
return tailrecsum(x - 1, running_total + x)
理论上类似上面:
tailrecsum(5, 0)
tailrecsum(4, 5)
tailrecsum(3, 9)
tailrecsum(2, 12)
tailrecsum(1, 14)
tailrecsum(0, 15)
15
观察到,tailrecsum(x, y)中形式变量y的实际变量值是不断更新的,对比普通递归就很清楚,后者每个recsum()调用中y值不变,仅在层级上加深。所以,尾递归是把变化的参数传递给递归函数的变量了
怎么写尾递归?形式上只要最后一个return语句是单纯函数就可以。如:
return tailrec(x+1);
return tailrec(x+1) + x;
则不可以。因为无法更新tailrec()函数内的实际变量,只是新建一个栈。

但Python不能尾递归优化(Java不行,C可以,我不知道为什么),这里是用它做个例子。
==================================== 如何优化尾递归
在编译器处理过程中生成中间代码(通常是三地址代码),用编译器优化。

【algorithm】尾递归的更多相关文章

  1. 挑子学习笔记:两步聚类算法(TwoStep Cluster Algorithm)——改进的BIRCH算法

    转载请标明出处:http://www.cnblogs.com/tiaozistudy/p/twostep_cluster_algorithm.html 两步聚类算法是在SPSS Modeler中使用的 ...

  2. PE Checksum Algorithm的较简实现

    这篇BLOG是我很早以前写的,因为现在搬移到CNBLOGS了,经过整理后重新发出来. 工作之前的几年一直都在搞计算机安全/病毒相关的东西(纯学习,不作恶),其中PE文件格式是必须知识.有些PE文件,比 ...

  3. [异常解决] windows用SSH和linux同步文件&linux开启SSH&ssh client 报 algorithm negotiation failed的解决方法之一

    1.安装.配置与启动 SSH分客户端openssh-client和openssh-server 如果你只是想登陆别的机器的SSH只需要安装openssh-client(ubuntu有默认安装,如果没有 ...

  4. [Algorithm] 使用SimHash进行海量文本去重

    在之前的两篇博文分别介绍了常用的hash方法([Data Structure & Algorithm] Hash那点事儿)以及局部敏感hash算法([Algorithm] 局部敏感哈希算法(L ...

  5. Backtracking algorithm: rat in maze

    Sept. 10, 2015 Study again the back tracking algorithm using recursive solution, rat in maze, a clas ...

  6. [Algorithm & NLP] 文本深度表示模型——word2vec&doc2vec词向量模型

    深度学习掀开了机器学习的新篇章,目前深度学习应用于图像和语音已经产生了突破性的研究进展.深度学习一直被人们推崇为一种类似于人脑结构的人工智能算法,那为什么深度学习在语义分析领域仍然没有实质性的进展呢? ...

  7. [Algorithm] 群体智能优化算法之粒子群优化算法

    同进化算法(见博客<[Evolutionary Algorithm] 进化算法简介>,进化算法是受生物进化机制启发而产生的一系列算法)和人工神经网络算法(Neural Networks,简 ...

  8. [Evolutionary Algorithm] 进化算法简介

    进化算法,也被成为是演化算法(evolutionary algorithms,简称EAs),它不是一个具体的算法,而是一个“算法簇”.进化算法的产生的灵感借鉴了大自然中生物的进化操作,它一般包括基因编 ...

  9. 尽量用goto代替尾递归

    void PrintList(List L) { if(L!=Null) { PrintElement(L->Element); PrintLisr(L->Next); } } 所谓尾递归 ...

随机推荐

  1. vscode 用户代码片段 vue初始化模板 Snippet #新加入开头注释 自动生成文件名 开发日期时间等内容

    vue文件模板 模板变量 https://code.visualstudio.com/docs/editor/userdefinedsnippets#_variables vue.json { // ...

  2. 解决WampServer窗口界面乱码问题

    软件版本:WampServer 3.1.4 问题描述:Wamp安装完成.点击图标,发现导航界面乱码,也可能使用中没遇到这种问题.如下: 用记事本打开 wampmanager.ini 和 wampman ...

  3. 位(bit)、字节(byte)、字

    1.位(bit)来自英文bit,音译为“比特”,表示二进制位.位是计算机内部数据储存的最小单位,11010100是一个8位二进制数.一个二进制位只可以表示0和1两种状态(21):两个二进制位可以表示0 ...

  4. 获取声音设备名称及PNPDeviceID

    实现效果: 知识运用: WMI管理类中的 ManagementObjectSearcher类 //基于指定的查询检索管理对象的集合 用于检索管理信息的较为常用的入口点之一 public Managem ...

  5. Caused by: java.lang.IllegalArgumentException: Parameter Maps collection does not contain value for com.bj186.crm.pojo.User

    原因分析: myBatis在写delete语句的时候,多写了一个属性 错误的代码: <delete id="deleteUser" parameterType="I ...

  6. 关于mysql服务突然运行不了的问题-“本地计算机上的mysql服务启动后停止,某些...”

    1.将mysql数据库的安装目录bin文件路径添加到环境的path中,为了让cmd可以直接输入下面的相关命令,不然cd到mysql的bin下也可以 2.cmd输入mysqld --initialize ...

  7. java内存模型(线程独占部分)

    线程独占部分 1.你了解Java的内存模型吗? 内存简介 有内核空间.用户空间(java是运行在用户空间上) 32位系统--->最大的访问内存大小是4G 62位系统--->最大的访问内存大 ...

  8. Android UI: LinearLayout中layout_weight 属性的使用规则

    首先来查看android sdk文档,有这么一段话 LinearLayout also supports assigning a weight to individual children with ...

  9. ios之@class

    objective-c中,当一个类使用到另一个类时,并且在类的头文件中需要创建被引用的指针时, 如下面代码: A.h文件 C代码   #import "B.h" @interfac ...

  10. 如何在Python中显式释放内存?

    根据Python官方文档,您可以强制垃圾收集器释放未引用的内存gc.collect().例: import gc gc.collect() 所属网站分类: python高级 > 综合&其 ...