×××××××××××××××××××××××××××××××××
菲波拉契数列的递归与非递归算法
转载
http://blog.csdn.net/sailor_8318/archive/2007/09/27/1802355.aspx
×××××××××××××××××××××××××××××××××
Fibonacci 数列有如下特点:其第 1 , 2 项均为 1 , 1 。从第 3 个数开始,该数是其前两个数之和 . 即 :
F1=1 (n=1)
F2=1 (n=2)
Fn=Fn-1+Fn-2 (n>=3)
请你编写一个函数 fun ,它的功能是:对于一个给定的数( N ), 求不大于 N 的最大 Fibonacci 数。
要保存两个连续的序列值,当前数大于且上一个小于时,即为所求值,非递归比较容易实现
1 1 2 3 5 8 13。。。。。。。。。。。。
×××××××××××××××××××××××××××××××××
递归算法:
1. 最普通算法
long fib(long n)
{
// if (n ==0 || n == 1)
if (n <= 0) // 因为上面的参数n是有符号的,要考虑容错性能,否则参数错误时将造成死循环了
return 0 ;
if ( n == 1)
return 1 ;
else
return fib(n – 1) + fib(n – 2);
}
2. 指针迭代,每次可算俩个值
fib(int n,int *s)
{
int f1,f2; // 每次递归都有申请两个变量,递归深度太大时可能导致堆栈溢出哦
if(n==1||n==2)
*s=1; 返回
else
{
fib(n-1,&f1); // 指针传递,这里只是将上面的一个式子分解了下而已
fib(n-2,&f2);
*s=f1+f2;
}
}
3. 引用迭代,减少了返回值临时变量的申请
fib(int n,int &s)
{
int f1,f2;
if(n==1||n==2)
s=1; 返回
else
{
fib(n-1, f1); // 引用传递
fib(n-2, f2);
s=f1+f2;
}
}
×××××××××××××××××××××××××××××××××
非递归算法
1. 数组迭代
void F(long*f, int n)
{
int i;
f[0]=f[1]=1;
if(n <= 2)
return;
for(i=2;i<n;i++)
f[i]=f[i-1]+f[i-2];
}
2. 变量替换,又额外申请了变量f0,f1,f2,不好;但每次更新相加的数,思想不错,逻辑清楚
void F(long *f, int n)
{
int f0,f1,f2;
f0=f1=1;
for(i=2;i<=n;++i){
f2=f0+f1;
f0=f1;
f1=f2;
}
printf(“f[%d]=%d/n”,n,f2);
}
3. 此法比较难以想到
对于任意第n项
int Fx(int n)
{
p1 = pow((1+sqrt(5))/2,n);
p2 = pow((1-sqrt(5))/2,n);
return (p1-p2)/sqrt(5);
}
4. 效率最高,一次循环可以算出两个值,每个值只需一条语句,没有交换过程,是通过改变输出的变量来实现的
void fibonacci(int n) // 1 2 3 …..
{
a = 1;
b = 1;
if(n <= 2)
{
cout << 1 << endl;
return;
}
for(i = 1; i < n/2; i++)
{
a += b; // a保存了奇数
cout << a << endl;
If((n > 3) && (n %2 == 0))// 每次的偶数部分
{
b += a; // b保存了偶数
cout << a << endl;
}
}
}
×××××××××××××××××××××××××××××××××
给定n,找到小于此数的最大fibonacci数
1. 变量替换,终止条件是当前数大于给定的数,上一个数就是求的临界值,c即为所求
void fibonacci(int n)
{
int a = 1;
int b = 1;
printf(“…”,a,b);
while(b<n)
{
int c=b;
b = a+b;
printf(“…”,b);
a = c;
}
}
2. 此法非常精妙,比上面少申请了一个中间变量c,通过加减来实现循环赋值的
#include <iostream.h>
void fibonacci(int n)
{
int low = 1,high = 1;
while(high < n)
{
cout << high << endl;
high = low + high;
low = high – low;
}
}