前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2020-1-6-什么是尾递归

2020-1-6-什么是尾递归

作者头像
黄腾霄
发布2020-06-10 15:06:54
2580
发布2020-06-10 15:06:54
举报
文章被收录于专栏:黄腾霄的博客黄腾霄的博客

递归算法想必大家都已经很熟悉了。递归算法虽然简单,但是容易导致一些性能问题,于是就有了尾递归这种优化算法。


首先我们先看看递归算法的性能问题是在哪里?

比如我们有一个常见的算法,叫做阶乘算法。

他的递归实现是这样子的

实现代码如下

代码语言:javascript
复制
//C#实现
int Foo(int x)
{
    if(x==1)
    {
        return 1;
    }
	return x*Foo(x-1);
}
代码语言:javascript
复制
#python 实现
def foo(x):
    if(x==):
        return 
    return x*foo(x-)

我们看到每次调用foo方法的时候,又会执行一次foo方法。

此时程序会将当前上下文压栈,计算出下一个foo的值,然后再出栈和x进行相乘

所以对于foo(3)的调用,整个栈的情况是这样的

那么尾递归呢?

它是指函数的最后一个位置(或者动作)是调用自身

我们把上面的方法改一下尾递归

代码语言:javascript
复制
//C#尾递归实现
int Foo(int x, int result=1)
{
    if(x==1)
    {
        return result;
    }
	return Foo(x-1,x*result);
}
代码语言:javascript
复制
#python 尾递归实现
def foo2(x,result=):
    if(x==):
        return result
    return foo2(x-,result*x)

这里有两个需要注意的点

  • 参数里面多了一个result,表示返回值。那么原本需要在内存中记录的信息,从方法参数中传入了
  • 最后的递归调用处位于return,递归的方法只需要返回一个值,而不需要同上一层递归调用的方法再做交互

那么这么有什么好处呢?

好处就是“聪明”的编译器在准备入栈时发现,咦,这里的递归放回值不需要做任何计算,直接返回更上一层就好了。那么存储上下文没有啥好处,不存了!!

所以此时的栈使用情况就会变成

内存占用,显著减少

不过尾递归虽好,但是还是要依赖于各种编译器的支持。

目前我知道的是python是支持的,探索c#之尾递归编译器优化 - 蘑菇先生 - 博客园文章中表示64位release下会进行尾递归优化


参考文档:


本文会经常更新,请阅读原文: https://xinyuehtx.github.io/post/%E4%BB%80%E4%B9%88%E6%98%AF%E5%B0%BE%E9%80%92%E5%BD%92.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名黄腾霄(包含链接: https://xinyuehtx.github.io ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-01-06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档