这个函数真的是尾递归吗?

时间:2013-04-20 01:43:04

标签: c++ c tail-recursion

我在编程访谈曝光(第3版)中读到了递归,其中它们呈现了以下递归factorial函数:

int factorial(int n){
    if (n > 1) { /* Recursive case */
        return factorial(n-1) * n;
    } else {     /* Base case */
        return 1;
    }
}

在同一页面的底部(第108页),他们讨论了尾递归函数:

  

请注意,当递归调用返回的值本身立即返回时,如前面factorial的定义,该函数是尾递归

但这是真的吗?函数中的最后一次调用是*调用,因此不会保留此堆栈帧(如果我们不考虑编译器优化)?这真的是尾递归吗?

4 个答案:

答案 0 :(得分:5)

您可以将其重写为尾递归:

int factorial(int n){
    return factorial2(n, 1);
}
int factorial2(int n, int accum) {
    if (n < 1) {
       return accum;
    } else {
        return factorial2(n - 1, accum * n);
    }
}

答案 1 :(得分:4)

不,它不是尾递归的。 factorial(n-1)返回的结果仍然必须乘以n,这需要factorial(n)重新获得控制权(因此要求factorial(n-1)的呼叫是呼叫而不是呼叫跳转)。

话虽如此,即使它是尾递归的,编译器仍然可能不会对它进行TCO。取决于您要求它执行的编译器和优化。

答案 2 :(得分:1)

从此链接引用:tail recursion using factorial as example

 factorial(n) {
    if (n == 0) return 1;
    return n * factorial(n - 1);
 }//equivalent to your code

 This definition is NOT tail-recursive since the recursive call to 
 factorial is not the last thing in the function 
 (its result has to be multiplied by n)

答案 3 :(得分:0)

Tail Recursive是递归的一种特殊情况,其中函数的最后一个操作是递归调用。在尾递归函数中,从递归调用返回时不执行待处理操作。 你提到的函数不是尾递归,因为有一个挂起的操作,即从递归调用返回时执行的乘法。 如果你这样做:

    int factorial(int n,int result)
    {
        if (n > 1)
        { /* Recursive case */
             return factorial(n-1,n*result);
        }
        else
        {     /* Base case */
            return result;
        }
    }

将是一个尾递归函数。因为它在递归调用返回时没有挂起操作。