• 递归和尾递归的区别


    非尾递归,下一个函数结束以后此函数还有后续,所以必须保存本身的环境以供处理返回值。

    尾递归,进入下一个函数不再需要上一个函数的环境了,得出结果以后直接返回。

    递归(迭代):

    
    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
    
    
    
    tailrecsum(5, 0)
    tailrecsum(4, 5)
    tailrecsum(3, 9)
    tailrecsum(2, 12)
    tailrecsum(1, 14)
    tailrecsum(0, 15)
    15
    

    尾递归的判断标准是函数运行最后一步是否调用自身,而不是是否在函数的最后一行调用自身。

    这是尾递归:

    
    function f(x) {
       if (x === 1) return 1;
       return f(x-1);
    }
    

    这不是尾递归:

    function f(x) {
       if (x === 1) return 1;
       return 1 + f(x-1);
    }
    
    

    通常递归都是在栈上根据调用顺序依次申请空间进行运算,然后层层回调,这是基于上一层运算依赖于下一层的运算结果(或者说上一层的运算还没用做完,需要下一层返回的结果)
    而尾递归的情况是下层计算结果对上层“无用”(上一层运算已经做完,不依赖后续的递归),为了效率,直接将下一层需要的空间覆盖在上一层上。

    所以

    尾递归,比线性递归多一个参数,这个参数是上一次调用函数得到的结果;
    所以,关键点在于,尾递归每次调用都在收集结果,避免了线性递归不收集结果只能依次展开消耗内存的坏处。

    使用尾递归可以带来一个好处:因为进入最后一步后不再需要参考外层函数(caller)的信息,因此没必要保存外层函数的stack,递归需要用的stack只有目前这层函数的,因此避免了栈溢出风险。

  • 相关阅读:
    Post提交和Get提交的区别
    Servlet 生命周期
    MVC
    HDU 5033 Building (维护单调栈)
    2014 ACM/ICPC Asia Regional Xi'an Online(HDU 5007 ~ HDU 5017)
    HDU 1026 Ignatius and the Princess I (BFS)
    URAL 1183 Brackets Sequence(DP)
    POJ 3384 Feng Shui(半平面交向内推进求最远点对)
    POJ 3525 Most Distant Point from the Sea (半平面交向内推进+二分半径)
    POJ 1279 Art Gallery(半平面交求多边形核的面积)
  • 原文地址:https://www.cnblogs.com/jackson1/p/12682659.html
Copyright © 2020-2023  润新知