【问题标题】:Recursive Functions Using Fibonacci Series [closed]使用斐波那契数列的递归函数
【发布时间】:2014-01-05 06:01:03
【问题描述】:

我正在自学 C++,来自 Sams Teach Yourself C++ In One Hour A Day,在第 150 页,作者使用斐波那契数列讨论了递归函数。

他使用以下代码:

#include <iostream>
using namespace std;

int GetFibNumber(int FibIndex)
{
    if(FibIndex < 2 )
        return FibIndex;
    else
        return GetFibNumber(FibIndex - 1) + GetFibNumber(FibIndex - 2);
}

int main()
{
    cout << " Enter 0 based index of desired Fibonacci Number: ";
    int Index = 0;
    cin >> Index;

    cout << " Fibonacci number is: " << GetFibNumber(Index) << endl;

    return 0;

}

有什么区别

return GetFibNumber(FibIndex - 1) + GetFibNumber(FibIndex - 2);

和

返回 FibIndex - 1 + FibIndex - 2;

为什么一定要在内部调用函数?

提前感谢您!

【问题讨论】:

  • 能否请您提供一个您所做的示例并更清楚地解释您的问题。
  • 第 9 行现在读到了什么?如果没有这两个函数调用,它将无法计算斐波那契数列。
  • 请看一下斐波那契数列是什么en.wikipedia.org/wiki/Fibonacci_number 没有最后一个GetFibNumber(FibIndex - 1) + GetFibNumber(FibIndex - 2) 计算是错误的。
  • @bkausbk 是的,我知道这一点。我只是删除了您刚刚复制和粘贴的行中的“GetFibNumber”。
  • @JOG-Design:只要输入参数 FibIndex 很小(

标签: c++ recursion fibonacci


【解决方案1】:

使用不使用递归的版本是不正确的。它只会正确计算前几个斐波那契数。尝试使用这两个版本计算前 10 个斐波那契数,您会发现这两个版本计算了两个不同的序列。

【讨论】:

    【解决方案2】:

    函数GetFibNumber 计算斐波那契数列中的第 N 个数。如果您只是看一下http://en.wikipedia.org/wiki/Fibonacci_number 上的解释,它是通过将斐宾那契数列中的 Nth-1 和 Nth-2 数字相加来计算的。这正是该函数的作用。您为函数提供要计算的斐波那契数列中的索引(假设为 6;结果应该为 8)。

    要计算斐波那契数列中的第 6 个元素,您需要将第 5 个和第 4 个元素相加。所以你首先需要计算这些。这就是递归介入的地方。你可以让函数自己调用;但现在不是使用值 6 作为参数再次调用它,而是使用 5 和 4。这将再次导致同样的问题(您需要通过添加元素 4 和 3 来计算第 5 个元素)等等。

    使用递归函数,您可以简单地重复使用代码来一遍又一遍地执行相同的计算,直到达到某个点,您可以得到计算的答案(在这种情况下,如果 N = 1 或 N = 0 ; 这些情况将导致 1).

    【讨论】:

      【解决方案3】:

      我建议,因为您仍在学习,所以既可以递归地编程(就像作者所做的那样),也可以使用循环(while,for)。它很可能会向您展示如何构建此算法的答案。

      提示 1:您必须知道斐波那契数列是建立在两个初始值之上...

      提示 2:对于递归,您应该知道函数结果是如何存储的。这也将解释您的问题。

      【讨论】:

        【解决方案4】:

        你问:“为什么你必须在内部调用函数?”好吧,严格来说,你没有。

        Fibonacci sequence 是这个数学递归定义的数字序列:

        • a0 = 0
        • a1 = 1
        • an = an-1 + an-2

        原始函数确实计算了这个序列,尽管效率低下。如果Index 为 0,则返回 0;如果为 1,则返回 1。否则返回 GetFibNumber(Index - 1) + GetFibNumber(Index - 2),这正是数学定义。对于序列的每个元素,您必须将序列中的前两项相加。

        您的代码只返回Index - 1 + Index - 2,这将给出不同的数字序列。比较:

        • 斐波那契:0、1、1、2、3、5、8、13、21、36...
        • 你的:0、1、1、3、5、7、9、11、13、17...

        但除此之外,您并不严格需要递归函数来计算此数学递归。您只需要一个简单的for 循环:

        int GetFibNumber(int FibIndex)
        {
        
            if(FibIndex < 2 )
                return FibIndex;
        
            int a_n_2 = 0, a_n_1 = 1, a_n;
        
            for (i = 2; i < FibIndex; i++)
            {
                a_n = a_n_1 + a_n_2;
                a_n_2 = a_n_1;
                a_n_1 = a_n;
            }
        
            return a_n;
        }
        

        这种方法也会更快。

        代码递归技术在数学上是正确的。然而,它比较慢,因为它不重用任何计算。它通过重做递归一直返回到 a1 来计算 an-1。然后它计算 an-2,而不重用任何生成 an-1 的工作。如果你考虑到递归的每一步都发生了这种缺乏重用,你会看到 running time grows exponentially for the recursive function. 它在 for 循环中线性增长。


        高级主题: 有一种方法可以使递归版本运行得更快,这对于了解您是否遇到最容易递归定义的编程问题非常重要。一旦您对 C++ 更加熟悉,请查找 memoization。记忆递归斐波那契给出线性的最坏情况运行时间,以及重复查找的恒定运行时间(假设备忘录查找本身是 O(1))。

        【讨论】:

        • 大声笑,知道他不必再像我建议的那样编写迭代程序了 :)
        • @RvdV79 :我想我们中的几个人都同时回答了这个问题。有时,我认为这样的问题是罗夏测验。 ;-)
        【解决方案5】:

        它们不是等价的,它肯定不会计算斐波那数序列。递归可以被认为是一棵树,所以要计算 Fib(8),根据定义,我们取 Fib(7) + Fib(6)

                Fib(8)
                /    \
            Fib(7)   Fib(6)
        

        这又需要计算 Fib(6), Fib(5), Fib(4) 如下:

                         Fib(8)
                       /        \
                  Fib(7)       Fib(6)
                /        \    /      \
             Fib(5)   Fib(6) Fib(5)  Fib(4)
        

        等等。你在做什么,会产生一个不同的、深度为 1 的树:

            Fib(8)
            /    \
           7      6
        

        因为,如果你从不在函数内部调用函数,它就永远不会更深入。从这个和其他答案中应该清楚为什么它不正确。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-07-27
          • 2020-03-21
          • 2012-11-19
          • 2021-02-17
          • 2021-12-01
          • 2016-11-07
          • 2012-02-16
          相关资源
          最近更新 更多