尾递归与尾调用

在很多的高级语言中,都会提到尾递归的特性。

当年在大学里学递归时,老师特别强调递归次数与进程栈的关系。

递归越多,函数入栈越多,由于进程有栈空间有线,会生成栈越界。

下图是一个入栈的过程。

main call funcA ;

funcA call funcB

当然了,递归引发栈越界只是调用栈越界的方式之一,如果代码写的调用层级特别多,则也会引发栈越界。

随着语言的发展(我想其中是语言的编译器与解释器的发展),发明一种叫“尾调用”的技术。

来个例子:

function B

{

    do someting;

    return 0;

}

function A

{

   do someting;

    return B;

}

这种A使用return B.把自己的返回与调用B联合在了一起。这就叫尾调用。

解释器就发现,当调用B完成之后,A的栈上的数据不会再被使用。那不如先把A从栈上POP出去。再调用B。

如下来个不是尾调用的例子。

function A1

{

   do someting;

   ret = B();

    return ret;

}

A1在调用了B后,还会使用栈上的内容。或是如下例子也不是尾调用。

function A2

{

   do someting;

      return B()+1;

}

尾调用不一定出现在函数尾部,只要是最后一步操作即可。

如function A3

{

      if(xxx == true) then

           return B(); //这里就是尾调用。

     else

           a++;

     end

}

尾调用的栈是怎么玩的呢?

尾递归正是使用了尾调用的特性。

在写递归函数时,特意使用尾调用的写法。这样递归时,栈空间不会随着递归次数而增长。这样就节约了很多的内存。


PS:我写的文章就很一般了,在网上有很多对尾调用和尾递归的介绍。大家可以多参考一下。

http://www.ruanyifeng.com/blog/2015/04/tail-call.html

C语言的编译器在加上-O2也可以识别并优化尾调用 。

有一例子,请大家自己行参考吧

http://blog.sina.com.cn/s/blog_5374d6e30100t0do.html


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值