【C语言】分别用递归和循环求斐波那契数列并比较它们的效率

在数学上,斐波那契数列以如下被以递推的方法定义:F(1)=0,F(2)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 3,n ∈ N*

1. 递归:

思路:

  • 递归公式: F(n) = F(n - 1) + F(n - 2)
  • 递归边界:n = 1或n = 2
代码:
long fibonacci(int n) {
    if(n == 1 || n == 2)    return 1;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

2. 循环:

思路:分别用两个变量始终指向F(n - 1)和F(n - 2)。

代码:
long fibonacci_loop(int n) {
    if(n == 1 || n == 2)    return 1;
    long a = 1, b = 1, tmp;   //用a指向F(i - 2),b指向F(i - 1)
    int i;
    for(i = 3; i <= n; i++) {
        tmp = b;
        b = a + b;  // 此时b = F(i) = F(i - 2) + F(i - 1)
        a = tmp;    // 此时a = F(i - 1)
    }
    return b;
}

3. 比较两种方法的性能:

  1. 时间复杂度:
    1.1 递归:O(2^n)
    1.2 循环:O(n)
  2. 效率:
    参考这篇博客,我导入了#include<time.h>头文件,利用clock()函数分别计算两个算法的执行时间。
代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

// 递归
long fibonacci(int n) {
    if(n == 1 || n == 2)    return 1;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

// 循环
long fibonacci_loop(int n) {
    if(n == 1 || n == 2)    return 1;
    long a = 1, b = 1, tmp;   //用a指向F(i - 2),b指向F(i - 1)
    int i;
    for(i = 3; i <= n; i++) {
        tmp = b;
        b = a + b;  // 计算F(i) = F(i - 2) + F(i - 1)
        a = tmp;    // 此时a = F(i - 1)
    }
    return b;
}

int main() {
    int n, i;
    time_t startTime, endTime, runtime1, runtime2;
    // 经实验得出:n < 3时,执行时间小于1ms,输出的执行时间都为0;n > 46时,输出结果超出long int的范围。所以n应该在[3, 46]中取。
    printf("Please input the total number of integers: (3 <= n <= 46)\n");
    scanf("%d", &n);

    // 调用递归算法
    startTime = clock();    // 计算执行时间,单位为毫秒
    for(i = 1; i <= n; i++) {
        printf("%ld ", fibonacci(i));
    }
	endTime = clock();
    runtime1 = endTime - startTime;
	printf("\n");
    printf("Recursive algorithm takes %ld ms to calculate the first %d fibonacci sequences respectively.\n\n", runtime1, n);

    // 调用循环算法
    startTime = clock();
    for(i = 1; i <= n; i++) {
        printf("%ld ", fibonacci_loop(i));
    }
	endTime = clock();
	runtime2 = endTime - startTime;
	printf("\n");
    printf("Loop algorithm takes %ld ms to calculate the first %d fibonacci sequences respectively.\n\n", runtime2, n);

    if(runtime1 < runtime2) printf("Therefore, the recursive algorithm is more efficient than the loop algorithm.");
    else if (runtime1 > runtime2)   printf("Therefore, the loop algorithm is more efficient than the recursive algorithm.");
    else    printf("Therefore, the recursive algorithm and the loop algorithm have the same efficiency");
    return 0;
}

输入:
40
输出结果:
Please input the total number of integers: (3 <= n <= 46)
40
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229 832040 1346269 2178309 3524578 5702887 9227465 14930352 24157817 39088169 63245986 102334155
Recursive algorithm takes 1245 ms to calculate the first 40 fibonacci sequences respectively.

1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229 832040 1346269 2178309 3524578 5702887 9227465 14930352 24157817 39088169 63245986 102334155
Loop algorithm takes 3 ms to calculate the first 40 fibonacci sequences respectively.

Therefore, the loop algorithm is more efficient than the recursive algorithm.

4. 总结:

  1. 在循环算法里,一开始我用的是int类型的变量,但当n比较大时,其斐波那契数列大小就超过2^31 - 1,所以我换成了long int类型的变量。
  2. 因为函数clock()返回值的单位为毫秒,如果n比较小,两个算法的执行时间都少于一秒,输出结果都为0,这样的性能比较没有意义。所以我比较两个算法计算前n个数的斐波那契数列需要的时间,这样时间差异就比较大了。
  3. n应该取[3, 46]之间的值,当n <= 2时,两个算法的执行时间都少于一秒,输出结果都为0。此外,当n > 46时,斐波那契数列的值超过了long int变量的范围。
  4. long int的输入、输出格式为%ld。time_t的变量类型为aka long int,其输入、输出也为%ld。
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值