【发布时间】:2013-04-20 01:43:04
【问题描述】:
我在 Programming Interviews Exposed(第 3 版)中读到了递归,其中介绍了以下递归 factorial 函数:
int factorial(int n){
if (n > 1) { /* Recursive case */
return factorial(n-1) * n;
} else { /* Base case */
return 1;
}
}
在同一页的底部(第 108 页),他们谈到了尾递归函数:
注意,当递归调用返回的值本身立即返回时,如前面
factorial的定义,函数是tail-recursive。
但这里真的是这样吗?函数中的最后一个调用是* 调用,所以这个栈帧不会被保留(如果我们不考虑编译器优化)?这真的是尾递归吗?
【问题讨论】:
-
这个函数确实不是尾递归的。
-
阶乘的朴素递归实现是非尾递归递归函数的经典示例,通常用于说明如何通过使用累加器获得尾递归......我建议你会得到一本不同的书。
-
你写“所以不会保留这个堆栈帧(如果我们不考虑编译器优化)” - 但是编译器优化与 this 函数无关,因为堆栈帧不能被消除...正是因为函数不是尾递归的。 Eric Jablow 给出了一个是尾递归的函数,因此堆栈帧可以被优化编译器消除。优化对于 C C++ 并不是那么重要,但对于像 F# 和 Haskell 这样的函数式语言来说是必不可少的,其中循环通常以递归方式实现。
-
@JimBalter:所以我认为没有编译器会优化它以使用累加器,从而使其成为尾递归? (实际上,确实听起来有点过头了,现在我想起来了……)
-
我对此表示怀疑,因为这样的重写可以任意复杂,具体取决于功能。
标签: c++ c tail-recursion