斐波那契函数问题

时间:2010-05-01 20:38:02

标签: c++ function

我正在计算Fibonacci序列,偶然发现了这段代码,我看了很多:

    int Fibonacci (int x)
{
    if (x<=1) {
        return 1;
    }
    return Fibonacci (x-1)+Fibonacci (x-2);
}

我不明白它是如何工作的,特别是最后的返回部分:它是否再次调用Fibonacci函数?有人可以引导我完成这个功能吗?

8 个答案:

答案 0 :(得分:16)

是的,该函数调用自身。例如,

Fibonacci(4)
= Fibonacci(3) + Fibonacci(2)
= (Fibonacci(2) + Fibonacci(1)) + (Fibonacci(1) + Fibonacci(0))
= ((Fibonacci(1) + Fibonacci(0)) + 1) + (1 + 1)
= ((1 + 1) + 1) + 2
= (2 + 1) + 2
= 3 + 2
= 5

请注意,Fibonacci函数在此处调用了9次。一般来说,天真的递归斐波纳契函数有exponential running time,这通常是一件坏事。

答案 1 :(得分:6)

这是一个recursive function的经典例子,这是一个自称的函数。

如果你仔细阅读,你会发现它会一遍又一遍地调用自己,或者 recurse ,直到它到达所谓的基本情况 ,当x <= 1时,它将开始“回溯”并总结计算值。

以下代码清楚地打印出算法的痕迹:

public class Test {

    static String indent = "";

    public static int fibonacci(int x) {

        indent += "    ";
        System.out.println(indent + "invoked with " + x);

        if (x <= 1) {

            System.out.println(indent + "x = " + x + ", base case reached.");
            indent = indent.substring(4);

            return 1;
        }

        System.out.println(indent + "Recursing on " + (x-1) + " and " + (x-2));
        int retVal = fibonacci(x-1) + fibonacci(x-2);
        System.out.println(indent + "returning " + retVal);
        indent = indent.substring(4);
        return retVal; 

    }


    public static void main(String... args) {
        System.out.println("Fibonacci of 3: " + fibonacci(3));
    }
}

输出如下:

invoked with 3
Recursing on 2 and 1
    invoked with 2
    Recursing on 1 and 0
        invoked with 1
        x = 1, base case reached.
        invoked with 0
        x = 0, base case reached.
    returning 2
    invoked with 1
    x = 1, base case reached.
returning 3

Fibonacci of 3: 3

跟踪的树状描述看起来像

                               fib 4
               fib 3             +           fib 2
    fib 2        +    fib 1              fib 1 + fib 0
fib 1 + fib 0           1                  1       1
  1       1

编写递归函数时要考虑的重要部分是:

<强> 1。照顾基本案例

如果我们在上面的示例中忘记了if (x<=1) return 1;,会发生什么?

<强> 2。确保递归调用以某种方式向基本情况减少

如果我们不小心修改了算法以返回fibonacci(x)+fibonacci(x-1);

,会发生什么

答案 2 :(得分:4)

  

返回Fibonacci(x-1)+ Fibonacci(x-2);

这非常低效。我建议采用以下线性替代方案:

unsigned fibonacci(unsigned n, unsigned a, unsigned b, unsigned c)
{
    return (n == 2) ? c : fibonacci(n - 1, b, c, b + c);
}

unsigned fibonacci(unsigned n)
{
    return (n < 2) ? n : fibonacci(n, 0, 1, 1);
}

斐波那契序列可以在函数式语言中更简洁地表达。

fibonacci = 0 : 1 : zipWith (+) fibonacci (tail fibonacci)

> take 12 fibonacci
[0,1,1,2,3,5,8,13,21,34,55,89]

答案 3 :(得分:3)

这是经典的函数递归。 http://en.wikipedia.org/wiki/Recursive_function应该让你入门。基本上如果x小于或等于1则返回1.否则它会减少x在每一步运行Fibonacci。

答案 4 :(得分:3)

由于你的问题标记为C ++,我觉得有必要指出,如果你有一个编译时变量可以在编译时使用它,这个函数也可以在编译时实现。

template<int N> struct Fibonacci {
    const static int value = Fibonacci<N - 1>::value + Fibonacci<N - 2>::value;
};
template<> struct Fibonacci<1> {
    const static int value = 1;
}
template<> struct Fibonacci<0> {
    const static int value = 1;
}

自从我写这篇文章以来已经有一段时间了,所以它可能会有点过时,但应该是它。

答案 5 :(得分:2)

是的,再次调用Fibonacci函数,这称为递归。

就像你可以调用另一个函数一样,你可以再次调用相同的函数。由于函数上下文是堆叠的,因此可以调用相同的函数而不会干扰当前执行的函数。

请注意,递归很难,因为您可以无限地再次调用相同的函数并填充调用堆栈。这个错误称为“堆栈溢出”(这里是!)

答案 6 :(得分:1)

在C和大多数其他语言中,允许函数像任何其他函数一样调用自身。这称为递归。

如果它看起来很奇怪,因为它与您要编写的循环不同,那么你是对的。这不是一个非常好的递归应用,因为找到 n 的Fibonacci数需要两倍的时间来找到 n -1th,导致中的运行时指数>名词

迭代Fibonacci序列,记住之前的Fibonacci数字,然后继续下一步将 n 中的运行时间改为线性,应该是这样。

递归本身并不可怕。实际上,我刚刚描述的循环(以及任何循环)可以实现为递归函数:

int Fibonacci (int x, int a = 1, int p = 0) {
    if ( x == 0 ) return a;
    return Fibonacci( x-1, a+p, a );
} // recursive, but with ideal computational properties

答案 7 :(得分:0)

或者,如果你想更快,但使用更多内存,请使用此功能。

int *fib,n;
void fibonaci(int n) //find firs n number fibonaci
{
 fib= new int[n+1];
 fib[1] = fib[2] = 1;
 for(int i = 3;i<=n-2;i++)
     fib[i] = fib[i-1] + fib[i-2];
}

并且对于例如n = 10,您将拥有:   fib [1] fib [2] fib [3] fib [4] fib [5] fib [6] fib [7] fib [8] fib [9] fib [10]     1 1 2 3 5 8 13 21 34 55``