尾递归

尾递归就是从最后开始计算, 每递归一次就算出相应的结果, 也就是说, 函数调用出现在调用者函数的尾部, 因为是尾部, 所以根本没有必要去保存任何局部变量,直接让被调用的函数返回时越过调用者。


比如计算n!

LL fac(int n,LL ans)
{
    return n == 1 ? ans:fac(n-1,ans*n);
}

上面的递归过程如下:

fac(5, 1)

fac(4, 5)

fac(3, 20)

fac(2, 60)

fac(1, 120)

120


很容易看出, 普通的线性递归比尾递归更加消耗资源, 在实现上说, 每次重复的过程调用都使得调用链条不断加长. 系统不得不使用栈进行数据保存和恢复。而尾递归就不存在这样的问题, 因为它的状态完全由n和ans保存.

 

经过实践证明尾递归要比传统的递归方法快得多。

LL fib(LL last,LL ans,LL cur,LL n)
{
    if(n == 1 || n == 2) return 1;
    if(cur == n) return ans;
    return fib(ans,ans+last,++cur,n);
}

比如,我们计算第6个Fib数的值,那么尾递归的调用过程为:


fib(0,1,0,6)

fib(1,1,1,6)

fib(1,2,2,6)

fib(2,3,3,6)

fib(3,5,4,6)

fib(5,8,5,6)

fib(8,13,6,6)


最终输出13

 

你可能感兴趣的:(尾递归)