我在编程访谈曝光(第3版)中读到了递归,其中它们呈现了以下递归factorial
函数:
int factorial(int n){
if (n > 1) { /* Recursive case */
return factorial(n-1) * n;
} else { /* Base case */
return 1;
}
}
在同一页面的底部(第108页),他们讨论了尾递归函数:
请注意,当递归调用返回的值本身立即返回时,如前面
factorial
的定义,该函数是尾递归。
但这是真的吗?函数中的最后一次调用是*
调用,因此不会保留此堆栈帧(如果我们不考虑编译器优化)?这真的是尾递归吗?
答案 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;
}
}
将是一个尾递归函数。因为它在递归调用返回时没有挂起操作。