C++ 两次调用自身作为回报——是否使用尾部递归?
我理解尾部递归,但是我被指派写一个代码来看看第N个斐波那契数是什么。 首先,这段代码确实有效。这不是最好的方法,但它是一种方法——不过我开始担心它不是尾部递归的。代码如下:C++ 两次调用自身作为回报——是否使用尾部递归?,c++,fibonacci,tail-recursion,C++,Fibonacci,Tail Recursion,我理解尾部递归,但是我被指派写一个代码来看看第N个斐波那契数是什么。 首先,这段代码确实有效。这不是最好的方法,但它是一种方法——不过我开始担心它不是尾部递归的。代码如下: static int fib_tail_helper(int n, int result) { if (n == 0) { return result; } else if (result == 0) { return fib_tail_helper(n - 1, result + 1); } else
static int fib_tail_helper(int n, int result) {
if (n == 0) {
return result;
}
else if (result == 0) {
return fib_tail_helper(n - 1, result + 1);
}
else {
return fib_tail_helper(n - 1, result + fib_tail_helper(n - 1, 0));
}
}
int fib_tail(int n) {
/*
// REQUIRES: n >= 0
// EFFECTS: computes the Nth Fibonacci number
// fib(0) = 0
// fib(1) = 1
// fib(n) = fib(n-1) + fib(n-2) for (n>1).
// MUST be tail recursive
*/
return fib_tail_helper(n, 0);
}
我最担心的是“返回fib\u tail\u helper(n-1,result+fib\u tail\u helper(n-1),0”。
我觉得这将使用另一个堆栈,因此是非尾部递归的…有人能提供一些输入吗
谢谢!!不,这不是尾部递归
编译器需要首先计算
fib\u tail\u helper
参数,这意味着在继续调用最后一个fib\u tail\u helper
作为返回值之前,它将创建n-1个调用堆栈。要显示它不是尾部递归,转换可能会有所帮助:
static int fib_tail_helper(int n, int result) {
if (n == 0) {
return result;
}
else if (result == 0) {
return fib_tail_helper(n - 1, result + 1);
}
else {
int tailrecursivePreventingValue = fib_tail_helper(n - 1, 0);
return fib_tail_helper(n - 1, result + tailrecursivePreventingValue);
}
}
它与您的代码完全相同,但引入了一个解释性变量。您可以看到,在最后一个else块中有两个对fib_tail_helper()的调用。这意味着指数运行时间,因为第二个值取决于第一个值。tail递归是递归的巧妙实现,它不使用堆栈空间 它的工作原理如下:
如果函数在最后一个动作中调用自身,则称为“尾部递归”。
在这种特殊情况下,编译器可以放弃执行实际的函数调用。它可以执行返回函数开头的
goto
。函数的代码将再次运行,就像它被调用一样。当函数终止时,它将返回堆栈上的最后一个地址,即最初调用递归函数
这种方法保证堆栈不会溢出,不管递归有多深。这就是尾部递归的优点
<坏消息是C++没有自动支持尾递归。< /P>
好消息是,实现尾部递归非常容易。只需将最后的函数调用替换为返回函数开头的
goto
。(如果编译器支持尾部递归,这只是您编写的
goto
。如果您想确保检查编译器输出。