我理解尾递归但是我被分配编写代码来查看N&#39斐波纳契数是多少。 首先,这段代码确实有效。这不是最好的方式,但它只是一种方式 - 但是我开始担心它不是尾递归。代码在这里:
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_tail_helper(n - 1,结果+ fib_tail_helper(n - 1),0 "。 我觉得好像会使用另一个堆栈,因此是非尾递归的...任何人都可以给出一些输入吗?
谢谢!
答案 0 :(得分:2)
不,它不是尾递归的。
编译器需要首先评估fib_tail_helper
参数,这意味着它会在继续调用最后一个fib_tail_helper
作为返回值之前创建n-1个调用堆栈。
答案 1 :(得分: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块中有2次调用fib_tail_helper()。这意味着指数运行时间,因为第二个值取决于第一个值。
答案 2 :(得分:0)
尾递归是一种巧妙的递归实现,它不使用堆栈空间。
它的工作原理如下:
如果一个函数调用自身,就像它的最后一个动作一样,则称为"尾递归"。
在这种特殊情况下,编译器可以放弃进行实际的函数调用。它可以执行goto
回到函数的开头。该函数的代码将再次运行,就像它已被调用一样。当函数终止时,它将返回堆栈的最后一个地址,这是最初调用递归函数的函数。
无论递归有多深,这种方法都可以保证堆栈不会溢出。这就是尾递归的好处。
坏消息是C ++不会自动支持尾递归。
好消息是实现尾递归非常容易
您只需将goto
的最终函数调用替换回函数的开头即可
(这只是你编写编译器所支持的goto
,如果它支持尾递归的话。)