斐波那契数列的递归和非递归算法

// 2014-04-20
// 斐波那契数列
// 算法速度 fbi4 > fbi3 > fbi2 > fbi1

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>

// 开始计时
void start_timer(struct timeval& tv)
{
    gettimeofday(&tv, 0);
}

// 流逝的时间(微秒)
long long get_time_elapse(struct timeval& tv)
{
    struct timeval tv2;
    gettimeofday(&tv2, 0);
    return (tv2.tv_sec-tv.tv_sec)*1000*1000 + (tv2.tv_usec - tv.tv_usec);
}

// 最常见的递归算法
int fbi1(int n)
{
    if (n < 2)
        return 0==n ? 0 : 1;

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

// 非递归算法
// 用一个缓冲区来保存每一个计算结果
int fbi2(int n)
{
    if (n < 2)
    {
        return 0==n ? 0 : 1;
    }

    int i = 0;
    int v = 0;
    int *buffer = (int *)malloc(sizeof(int) * n);
    buffer[0] = 1;
    buffer[1] = 1;

    for (i=2; i<n; ++i)
    {
        buffer[i] = buffer[i-2] + buffer[i-1];
//        printf("%d + %d = %d\n", buffer[i-2], buffer[i-1], buffer[i]);
    }
    v = buffer[i-1];
    free(buffer);
    buffer = 0;

    return v;
}

inline int next(int n)
{
    ++n;
    return n%3;
}

// 改进版本,节约内存
// 用一个环形缓冲区来保存前面两个计算结果
int fbi3(int n)
{
    if (n < 2)
    {
        return 0==n ? 0 : 1;
    }

    int a = 0;
    int b = 1;
    int c = 2;
    int buffer[3] = {1, 1, 2};

    for (int i=2; i<n; ++i)
    {
        buffer[c] = buffer[a] + buffer[b];
//        printf("%d + %d = %d\n", buffer[a], buffer[b], buffer[c]);

        a = next(a);
        b = next(b);
        c = next(c);
    }

    return 0==c ? buffer[2] : buffer[c-1];
}

// 再次改进,不使用缓冲区
// 一次循环算出两个
int fbi4(int n)
{
    if (n < 2)
    {
        return 0==n ? 0 : 1;
    }

    int a = 1;
    int b = 1;
    int c = 2;
//    int m = n;

    // n = (n+1)/2 + 1;
    ++n;
    n >>= 1;
    ++n;

    for (int i=2; i<n; ++i)
    {
        c = a + b;
//        printf("%d + %d = %d\t", a, b, c);

//        int t = b;
        a = c;
        b = a + b;
//        printf("%d + %d = %d\n", a, t, b);
    }
//    printf("n=%d, a=%d, b=%d, c=%d\n", m, a, b, c);
    n = (n%2) ? b : a;
    return n;
}

#define __test_fbi(n, v) do {\
        struct timeval tv;\
        start_timer(tv);\
        printf("fbi%d, %d = %lld\n", n, v, fbi##n(v));\
        printf("time: %lld us\n", get_time_elapse(tv));\
    } while (0)

void test_fbi()
{
    int n = 41;
    __test_fbi(1, n);
    __test_fbi(2, n);
    __test_fbi(3, n);
    __test_fbi(4, n);

//    for (int i=0; i<100; ++i)
//    {
//        printf("%d\t", i);
//        printf("%d\t", fbi1(i));
//        printf("%d\t", fbi2(i));
//        printf("%d\t", fbi3(i));
//        printf("%d\n", fbi4(i));
//    }
}

int main()
{
    test_fbi();

    return 0;
}
算法测试结果
fbi1(40) = 102334155
time: 1527967 us
fbi2(40) = 102334155
time: 96 us
fbi3(40) = 102334155
time: 11 us
fbi4(40) = 102334155
time: 10 us


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值