斐波那契数列介绍:斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)
根据以上的递推公式,我们很容易可以得到递归的解决办法
实现代码:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int Fib(int n) {//用递归实现斐波那契数列
int result;
if (n == 1 || n == 2) {
return 1;
}
result = Fib(n - 1) + Fib(n - 2);
return result;
}
int main() {
int n;
scanf("%d", &n);
int ret=Fib (n);
printf("ret=%d\n", Fib(n));
system("pause");
return 0;
}
由代码可以看出递归的办法非常简短,直接将斐波那契数列的递推公式带入即可实现,但与此同时这个办法也有一个缺点,那就是效率低下,当n较大时,计算斐波那契数需要很长时间,这是因为程序在每次递归调用自己时都需要算一遍n-1和n-2项,存在很多重复计算,我们可以使用代码来看一下,当计算n为40的斐波那契数时,要做多少次运算。(暂且不考虑溢出的情况)
int count = 0;
int Fib(int n) {//用递归实现斐波那契数列
int result;
if (n == 1 || n == 2) {
return 1;
}
if (n == 3) {
++count;
}
result = Fib(n - 1) + Fib(n - 2);
return result;
}
增加一个变量count,通过这个变量的值来看一下n为40时的运算次数
我们可以发现运算量实在太大了,那怎么解决这样的问题呢,我们可以使用非递归的办法来求斐波那契数列。
实现代码:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int Fib2(int n) {
if (n == 1 || n == 2) {
return 1;
}
int last2 = 1;//第i-2项
int last1 = 1;//第i-1项
int result = 0;
for (int i = 3; i <= n;++i) { //每次循环都要更新前一项与前两项的值
result = last1 + last2;
last2 = last1;
last1 = result;
}
return result;
}
int main() {
int n;
scanf("%d", &n);
int ret=Fib(n);
printf("ret=%d\n", Fib (n));
system("pause");
return 0;
}
前一个递归之所以效率低是因为重复计算的原因,那如果可以避免掉这样的重复计算,递归方法还是可以提高效率的。
实现代码:
#include<stdio.h>
#include<stdlib.h>
int Fib(int n, int last2, int last1) {
if (n == 2|| n==1) {
return last1;
}
return Fib(n - 1, last1, last1 + last2);
}
int main() {
//int n;
//scanf("%d", &n);
int ret = Fib(9, 1, 1);
printf("%d\n", ret);
system("pause");
return 0;
}
增加了函数参数,每次将计算结果存到last1中,最后返回last1的值,即可得到相应的斐波那契数。
n=9时的运行结果: