// 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