递归函数是否比非递归函数慢

时间:2017-03-25 11:15:00

标签: c++ recursion

我使用了一个递归函数来表示数字的阶乘和Fibonacci系列(在C ++中完成),我发现关于阶乘的递归函数运行正常,并且执行速度没有太大差别。

然而在Fibonacci上,它决定性地缓慢。为什么会这样?

递归方法:

unsigned long int fib_num(int n)  //This is My code
{
    switch (n)
    {
    case 1:
        return 0;
        break;
    case 2:
        return 1;
        break;
    default:
        return fib_num(n - 1) + fib_num(n - 2);
        break;
    }
}

迭代方法:

first = 0;
second = 1

for(i = 0; i < num; i++)   
{
    cout<<"\n"<<first;

    next = first + second;

    first = second;
    second = next;
}

2 个答案:

答案 0 :(得分:1)

你的观察是正确的,计算中的递归方法,在这种情况下,斐波纳契数,如果仔细观察会导致从一开始就计算Fibonacci的每一项,即

例如,要计算F [n] + F [n-1],该函数会分别计算两个项,并且它会多次执行相同的工作。

示例:F [5] = F [4] + F [3]

计算F [3]:程序计算:F [2],F [1],F [1],F [0]

计算F [4]:程序再次计算:F [2],F [2],F [1],F [1],F [0],F [0]和F [3] < / p>

以下是您的函数调用的图形:

enter image description here

这导致你的观察,即在每次递归调用时,工作量增加一倍,导致复杂性:O(2 n )。

避免上述情况的一种可能方法是使用memoization:

// header needed for the container: map
#include <map> 

int mem_fact (int i, std::map<int, int>& m)
{
    // if value with key == i does not exist in m: calculate it
    if (m.find(i) == m.end()) 
    {
        // the recursive calls are made only if the value doesn't already exist
        m[i] = mem_fact (i - 1, m) + mem_fact (i - 2, m); 
    }

    // if value with key == i exists, return the corresponding value
    return m[i];
}

int fast_factorial (int i)
{
    // key (Fibonacci index) - value (Fibbonaci number)
    std::map<int, int> memo;

    // initialize the first two Fibonacci numbers
    memo.insert(std::pair<int,int>(0, 0));
    memo.insert(std::pair<int,int>(1, 1));

    return mem_fact(i, memo);
}

注意:在main()中,您需要致电fast_factorial(num_of_fib);

答案 1 :(得分:0)

我将举一个Fibion​​acci系列的例子。

recursive 41 index calculated pass time 1.343 seconds
non recursive 40000 index calculated pass time 1.042 seconds

这是我们的代码。

public static void main(final String[] args) {

    long before = new Date().getTime();
    for(int i = 0; i <= 41; i++) {
        findRecursiveFibionacci(i);
    }
    System.out.println("recursive 41 index calculated pass time "+((float)(new Date().getTime()-before)/1000) + " seconds");

    long before2=new Date().getTime();
    for(int i = 0; i <= 40000; i++) {
        getFib(i);
    }
    System.out.println("non recursive40000 index calculated pass time "+((float)(new Date().getTime()-before2)/1000) + " seconds");
}

public static long getFib(final int index) {
    long a=0,b=0,total=0;
    for(int i=0;i<= index;i++) {
        if(i==0) {
            total=a+b;
            a=0;
        }else if(i==1) {
            b=1;
            total=a+b;

        }else if(i%2==0) {
            total=a+b;
            a=total;
        }else {
            total=a+b;
            b=total;
        }
    }
    return total;
}

public static long findRecursiveFibionacci(final int a ){
    if(a==0)return 0;
    if(a<=2)return 1;
    final long fibterm = findRecursiveFibionacci(a-1)+findRecursiveFibionacci(a-2);
    return fibterm;
}