在此示例中,如何仅打印序列一次? (递归函数)

时间:2018-05-30 00:01:39

标签: c recursion

只是一个斐波纳契算法,我如何打印每一个斐波那契数列而不重复每一步?

递归函数是否适用于任何方式?我知道它更清晰,但如果我把n = 40,这个简单的算法有一个明显的延迟,而这样做的迭代方法是瞬时的。

int fib(int n)
{   
    if (n == 0)
    {
        return 0;
    }
    else if (n == 1)
    {
        return 1;
    }

    return fib(n - 1) + fib(n - 2);
}

2 个答案:

答案 0 :(得分:1)

您可以通过记忆已经计算的值来轻松优化递归解决方案:

int fib(int n) {
    static int cache[48] = {0}; // should be enough to hold all int fibs
    if(n < 2) return n; // initial conditions
    else if(cache[n]) return cache[n]; // a value already computed and memoized
    else return cache[n] = fib(n - 1) + fib(n - 2); // the largest so far
}

应该加速计算,呃,某个因素。

答案 1 :(得分:0)

像C这样的命令式语言并不总能很好地映射到算法的功能定义。

非递归通常更快,因为编译器和处理器都可以更容易地优化/并行化执行,并且您不会浪费能量,不必要地推送和弹出堆栈。无论哪种方式,您只需要前两个fib值来计算下一个:

void PrintNFibs(unsigned n)
{
    size_t a = 1;
    size_t b = 1;
    size_t sum;
    printf("0\n1\n1\n");
    while ( n-- )
    {
        sum = a + b;
        printf("%zu\n", sum);
        a = b;
        b = sum;
    }
}

根据自身(递归)定义算法是一回事,而在C中有效地实现算法。对于像Fibonacci这样简单的事情,我不会使用递归,但不管怎么说这是一个:

void PrintNFibsR(unsigned n)
{
    static size_t a = 0;
    static size_t b = 1;
    static size_t sum;
    sum = a + b;

    if ( a == 0 )
    {
        printf("0\n1\n");
    }

    printf("%zu\n", sum);
    if ( n > 1 )
    {
        a = b;
        b = sum;
        PrintNFibsR(n - 1);
    }
}

请注意,我们在这里所做的一切都是通过循环计数器。如果没有实际功能,那么浪费但技术上是递归的。编写看起来就像递归Fibonacci算法定义的C代码的问题是它没有充分的理由燃烧能量和堆栈空间。您可以在不事先计算和存储每个值的情况下以正确顺序打印值的唯一方法是更改​​算法。