【algorithm】尾递归
尾递归和一般的递归不同在对内存的占用,普通递归创建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】尾递归的更多相关文章
- 挑子学习笔记:两步聚类算法(TwoStep Cluster Algorithm)——改进的BIRCH算法
转载请标明出处:http://www.cnblogs.com/tiaozistudy/p/twostep_cluster_algorithm.html 两步聚类算法是在SPSS Modeler中使用的 ...
- PE Checksum Algorithm的较简实现
这篇BLOG是我很早以前写的,因为现在搬移到CNBLOGS了,经过整理后重新发出来. 工作之前的几年一直都在搞计算机安全/病毒相关的东西(纯学习,不作恶),其中PE文件格式是必须知识.有些PE文件,比 ...
- [异常解决] windows用SSH和linux同步文件&linux开启SSH&ssh client 报 algorithm negotiation failed的解决方法之一
1.安装.配置与启动 SSH分客户端openssh-client和openssh-server 如果你只是想登陆别的机器的SSH只需要安装openssh-client(ubuntu有默认安装,如果没有 ...
- [Algorithm] 使用SimHash进行海量文本去重
在之前的两篇博文分别介绍了常用的hash方法([Data Structure & Algorithm] Hash那点事儿)以及局部敏感hash算法([Algorithm] 局部敏感哈希算法(L ...
- Backtracking algorithm: rat in maze
Sept. 10, 2015 Study again the back tracking algorithm using recursive solution, rat in maze, a clas ...
- [Algorithm & NLP] 文本深度表示模型——word2vec&doc2vec词向量模型
深度学习掀开了机器学习的新篇章,目前深度学习应用于图像和语音已经产生了突破性的研究进展.深度学习一直被人们推崇为一种类似于人脑结构的人工智能算法,那为什么深度学习在语义分析领域仍然没有实质性的进展呢? ...
- [Algorithm] 群体智能优化算法之粒子群优化算法
同进化算法(见博客<[Evolutionary Algorithm] 进化算法简介>,进化算法是受生物进化机制启发而产生的一系列算法)和人工神经网络算法(Neural Networks,简 ...
- [Evolutionary Algorithm] 进化算法简介
进化算法,也被成为是演化算法(evolutionary algorithms,简称EAs),它不是一个具体的算法,而是一个“算法簇”.进化算法的产生的灵感借鉴了大自然中生物的进化操作,它一般包括基因编 ...
- 尽量用goto代替尾递归
void PrintList(List L) { if(L!=Null) { PrintElement(L->Element); PrintLisr(L->Next); } } 所谓尾递归 ...
随机推荐
- PHP 中空字符串介绍0、null、empty和false之间的关系
0是数字,是empty,是false,不是null,值相当于空字符串,但类型不是字符串,去空格或强制转换为字符串型时不等于空字符串 ""的值相当于0,是empty,是空字符串,是f ...
- node.js中使用Redis
服务端: 启动Redis服务: redis-server 客户端: 1.安装Redis npm install redis --save 2.redisTest.js文件 //引入red ...
- SQL 中 NOT IN 查询不到数据
一.问题 用以下sql语句查询数据,结果为空 SELECT a.ID , a.Sub_Project_Name , a.Sub_Project_Type FROM TB_KYSubProject a ...
- TWaver3D直线、曲线、曲面的绘制
插播一则广告(长期有效) TWaver需要在武汉招JavaScript工程师若干 要求:对前端技术(JavasScript.HTML.CSS),对可视化技术(Canvas.WebGL)有浓厚的兴趣 基 ...
- WebGL 绘制Line的bug(一)
今天说点跟WebGL相关的事儿,不知道大家有没有碰到过类似的烦恼. 熟悉WebGL的同学都知道,WebGL绘制模式有点.线.面三种:通过点的绘制可以实现粒子系统等,通过线可以绘制一些连线关系:面就强大 ...
- centos 7 安装 docker(详细)
更新源 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup wget -O/etc/yum.re ...
- 四、StaticList 和 DynamicList
1.StaticList类模板 StaticList的设计要点:类模板 使用原生数组作为顺序存储空间 使用模板参数决定数组大小 template <typename T, int N> c ...
- 我的Python分析成长之路1
Python是什么? ...
- ActiveMQ windows安装
下载ActiveMQ 官方网站:http://activemq.apache.org/ 下载,解压缩 以前台安装 ctiveMQ默认使用的TCP连接端口是61616, 通过查看该端口的信息可以测试Ac ...
- Python数据结构--搜索树
''' 二叉搜索树(BST)是一棵树,其所有节点都遵循下述属性 - 节点的左子树的键小于或等于其父节点的键. 节点的右子树的键大于其父节点的键. 因此,BST将其所有子树分成两部分; 左边的子树和右边 ...