C语言实现求解斐波那契数列的四种方法及优化处理(递归,迭代,特殊性质公式,矩阵快速幂)
众所周知,斐波那契数列是非常经典的一个数列,它的数学公式如下
为了便于观察,我们列出它的几项:0 1 1 2 3 5 8 13 21......
下面我们将介绍四种方法来用C语言计算机代码实现对斐波那契数列的求解,分别是:递归法,迭代法,矩阵求解法以及特殊性质公式。
一、递归法
(PS:没有递归基础的建议先学习递归的基础概念,在此我仅简要介绍一下递归的思想和求解代码)
在递归的实现中,我们知道,递归有两个要求:(1)进行递归这一操作所需要满足的条件 (2)此条件需要最终不被满足,使得函数的嵌套调用能够返回。在斐波那契数列中,我们知道当x=0时,返回值为0;当x=1时,返回值为1。所以,要求(1)中所需要满足的条件即x>=2;而要求(2)中要使该条件最终不被满足,即x不断减小,且最终为0或1。
于是我们给出代码的实现:
int Fibonacci(int x)
{if (x >= 2)return Fibonacci(x - 1) + Fibonacci(x - 2); //当x>=2时,继续按照公式f(x)=f(x-1)+f(x-2)嵌套调用else if (x == 1)return 1; //当x=1时,返回1,同时嵌套调用开始返回elsereturn 0; //当x=0时,返回0,同时嵌套调用开始返回
}
用递归的方法求解斐波那契数列是不是非常简单呢?
然而! 用递归的方法也有一个很大的缺点:栈溢出!
栈:函数及其形参的空间由栈分配,在函数调用未完成时,为其分配的空间并不会销毁!于是当递归中函数的调用次数过多时,会导致栈溢出的问题。在本题的递归中,我们能发现,当我们求
F(5)= F(4)+F(3)
= F(3)+F(2)+F(2)+F(1)
= F(2)+F(1)+F(1)+F(0)+F(1)+F(0)+F(1)时,不仅对F(2)进行了多次调用,甚至还进行了多次计算!这就导致计算效率的大幅降低以及资源占用的大幅增加。
于是我们给出第二种方法。
二、迭代法
什么是迭代法?
迭代法也称辗转法,是一种不断用变量的旧值递推新值的过程。
也就是说,这是一种各个变量直接相互作用的过程。
分析思路:设有a、b、c三个变量,以及我们输入的第x项的x,令a=0(第一个斐波那契数)b=1(第二个斐波那契数),当x>=2时,c=a+b,同时再令a、b分别往右移一个数,如此往复x-2次,c的值就变成了第x个数的值。
下面给出代码:
int Fibonacci(int x)
{int a = 0;int b = 1;int c = 0;if (x == 1)return 1; //当x=1,返回1if (x == 0)return 0; //当x=0,返回0while (x >= 2) //输入x>=2时,进行迭代{c = a + b; //每次迭代令c=a+b,即进行f(x)=f(x-1)+f(x-2)a = b; //使得a,b往后移一个数字b = c;x--;}return c;
}
三、特殊性质公式法
同递归法,只不过需要用到公式:
F(n+m)=F(m)*F(n+1)+F(m-1)*F(n)
在这个公式下,F(x)可以转换为F((x/2) + x-(x/2)),即一种二分思想,可以将时间复杂度为O(n)的算法转化为时间复杂度为O(log n)的算法。
下面给出代码:
int Fibonacci(int x)
{if (x == 1 || x == 2) //当x=2时也要返回1,否则将进入死循环。return 1;if (x == 0)return 0;int a = x / 2;int b = x - a;return Fibonacci(a + 1) * Fibonacci(b) + Fibonacci(a) * Fibonacci(b - 1);
}
然而虽然但是事实上这个方法还是不如迭代法来得实在的QoQ
四、矩阵法
于是,只要先算出系数矩阵的n-1次幂,再用与之相乘即可求出F(n)
下面是用矩阵快速幂的方法求出所需矩阵n-1次幂的代码:
(PS:小编只学了快速幂,这个矩阵快速幂的算法是自己琢磨出来的,可能不标准,如果有心可以去学一下矩阵快速幂的算法!!下面会给出一般快速幂的算法给各位小可爱们参考一下~)
int Fibonacci(int x)
{if (x == 0)return 0;if (x == 1 || x == 2)return 1;int a[2][2] = { {1,1},{1,0} };int b[2][2] = { {1,1},{1,0} };int c[2][2] = { {1,0},{0,1} };int d[2][2] = { {1,0},{0,1} };int t = x - 1;while (t){if (t%2==1){d[0][0] = c[0][0] * b[0][0] + c[0][1] * b[1][0];d[0][1] = c[0][0] * b[0][1] + c[0][1] * b[1][1];d[1][0] = c[1][0] * b[0][0] + c[1][1] * b[1][0];d[1][1] = c[1][0] * b[0][1] + c[1][1] * b[1][1];c[0][0] = d[0][0];c[0][1] = d[0][1];c[1][0] = d[1][0];c[1][1] = d[1][1];}b[0][0] = a[0][0] * a[0][0] + a[0][1] * a[1][0];b[0][1] = a[0][0] * a[0][1] + a[0][1] * a[1][1];b[1][0] = a[1][0] * a[0][0] + a[1][1] * a[1][0];b[1][1] = a[1][0] * a[0][1] + a[1][1] * a[1][1]; a[0][0] = b[0][0];a[0][1] = b[0][1];a[1][0] = b[1][0];a[1][1] = b[1][1];t >>= 1;}return c[0][0];
}
其中F(x) = c[0][0]*F(1)+c[1][0]*F(0) = c[0][0]
快速幂代码:
int f(int a,int n)
{int ans = 1;while (n){if (n & 1 == 1) //判断n的最后一位是否为1{ans *= a;}a *= a; //a每次自乘a,使得a在每次循环中分别为a,a^2,a^3...n >>= 1; //n右移一,使得n的二进制表示中1所在的位置所代表的位全与a当前的次幂相同}return ans;
}
好啦这就是全部内容啦!!!
C语言实现求解斐波那契数列的四种方法及优化处理(递归,迭代,特殊性质公式,矩阵快速幂)相关推荐
- Python中斐波那契数列的四种写法
在这些时候,我可以附和着笑,项目经理是决不责备的.而且项目经理见了孔乙己,也每每这样问他,引人发笑.孔乙己自己知道不能和他们谈天,便只好向新人说话.有一回对我说道,"你学过数据结构吗?&qu ...
- 剑指offer——面试题9:求斐波那切数列的四种方法
剑指offer--面试题9:求斐波那切数列的四种方法 另一个相关的链接:https://blog.csdn.net/Allenlzcoder/article/details/80297333 总结下求 ...
- C语言--斐波那契数列(三种方法)
文章目录 一·介绍 二·代码实现 1·递归实现 2·迭代实现 3·数组实现 一·介绍 斐波那契数列,就是前两个数是1,之后从第三个数开始等于前面两个数的和,请用代码方式求出第n个斐波那契数列的大小. ...
- C语言斐波那契数列求和两种方法
递归调用函数: #define _CRT_SECURE_NO_WARNINGS int fun(int n); #include<stdio.h> int main() {//斐波那契数列 ...
- 斐波那契数列的四种实现方式(C语言)
斐波那契数列是一组第一位和第二位为1,从第三位开始,后一位是前两位和的一组递增数列, 像这样的:1.1.2.3.5.8.13.21.34.55...... 今天,我们用四种方式来进行实现: 1.递归 ...
- C语言实现斐波那契数列的几种方法
斐波那契数列指的是这样一个数列:1 .1.2.3.5.8.13.21.34.55.89--是从第三项开始每一项都是前两项之和. 用递推的方法定义为: f(0)=1;f(1)=1; f(n)=f(n-1 ...
- 剑指Offer #07 斐波那契数列(四种解法)| 图文详解
题目来源:牛客网-剑指Offer专题 题目地址:斐波那契数列 题目描述 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0).n<=39 题目解析 ...
- 斐波那契数列的四种实现
来自:Crossin的编程教室 孔乙己自己知道不能和他们谈天,便只好向 Intern 说话.有一回对我说道,"你写过代码么?"我略略点一点头.他说,"写过代码,--我便考 ...
- C++输出斐波那契数列的几种方法
定义: 斐波那契数列指的是这样一个数列:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ... 这个数列从第三项开始,每一项都等于前两项之和. 以输出斐波那 ...
最新文章
- 【转】C++的面象对象总结
- opencv4 c++ 提取图片中的白色区域_修正!【从零学习OpenCV 4】分割图像——分水岭法...
- 《算法竞赛进阶指南》打卡-基本算法-AcWing 97. 约数之和:递归、快速幂
- zabbix如何选择适合的监控类型(107)
- jmeter进行https协议的测试
- android-线程池-最顺手的写法
- LeetCode 1566. 重复至少 K 次且长度为 M 的模式
- 职称计算机承诺书,职称申报承诺书范本
- php而且,PHP – David's Blog
- 分享一个Ubuntu16.0.4安装MySQL5.7脚本
- 工具的使用——搜狗输入法
- Android5更新包,Android5.1无法完成整包的更新
- 如何构建NTP时间服务器
- podman加速器harbor私有镜像仓库
- testbed代码审查信息提取
- [gitHub使用笔记一]ubuntu下快速访问github官网的方法
- 小伙伴们要的飞机大战代码 简易入门版
- 桂电计算机系入学怎么分班,桂电研究生-()学期课程总表
- 计算机上安装了更新ie版本,电脑XP系统安装不了ie提示“安装了更新的Internet Explorer版本”的解决方法...
- Windows Update错误80070003解决方法