目录
斐波那契数列指的是这样一个数列:1,1,2,3,5,8,13,21,34,55,89,从第三项开始每一项都是前两项的和。
斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下被以递推的方法定义:F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)
上述文献来自百度百科——斐波那契数列
这个是一个递归的经典问题,分解来看每一项的得数都是前两项的和,只有前两项为1,所以得出以下的递归程序。
int Fib(int n)
{
count++;
if (n <= 2)
return 1;
else
return Fib(n - 1) + Fib(n - 2);
}
但是,由于每一次递归都要在内存栈区开辟一块空间用来满足递归函数的需要,所以如果数字过大,可能会产生栈溢出的现象,我们设置一个全局变量count来观察一下递归40次的时候,此时count已经达到了一个非常大的次数。
造成这种现象的原因可以通过以下图示来分析一下,以Fib(5)来举例子,我们发现,每一个Fib函数当参数没有达到1或者2的时候都要往下接着调用两次自身,所以计算的过程大致为2的次方的大小,这个数字每增加一就会乘二,增长速度很快。
那么,为了解决如果数字比较大栈区溢出的问题,我们想到能否使用递归以外的方法完成这个数列的计算呢,于是我们想到了使用循环来解决这个问题。代码如下
int fib_no(int n)
{
if (n <= 2)
return 1;
else
{
int first = 1;
int second = 1;
int third = 1;
while (n > 2)
{
third = first + second;
first = second;
second = third;
n--;
}
return second;
}
}
当n小于2的时候输出1,当n大于2的时候通过反复相加得到我们要的结果。
完整代码如下所示
#include<stdio.h>
//1.斐波那契数列1 1 2 3 5 8 11
int count = 0;
int Fib(int n)
{
count++;
if (n <= 2)
return 1;
else
return Fib(n - 1) + Fib(n - 2);
}
int Fib_no(int n)
{
if (n <= 2)
return 1;
else
{
int first = 1;
int second = 1;
int third = 1;
while (n > 2)
{
third = first + second;
first = second;
second = third;
n--;
}
return second;
}
}
int main()
{
int num = 0;
printf("num=");
scanf("%d", &num);
printf("Fib=%d\n Fib_no=%d\n", Fib(num),Fib_no(num));
printf("count=%d", count);
return 0;
}
与斐波那契数列相似的问题还有青蛙跳台阶的问题,问题描述如下
一只小青蛙一次可以跳一个台阶或者两个台阶,给定一个台阶数,小青蛙跳完这个台阶总共有多少种跳法呢。
对这个问题进行分解,与斐波那契数列有相似之处,不同点在于当num=2的时候有跳两次一个台阶和跳一次两个台阶的情况,所以返回值有所不同。
int Frog_step(int num)
{
if (num ==1 || num==2)
{
return num;
}
else
{
return Frog_step(num - 1) + Frog_step(num - 2);
}
}