递归与迭代(循环)
练习NO1.
//求n的阶乘。(不考虑溢出)
#include<stdio.h> int Fac(int i) { if (i <= 1) return 1; else return i * Fac(i - 1); } int main() { int i = 0; scanf("%d", &i); int ret = Fac(i); printf("%d\n", ret); return 0; }
根据数学公式,我们可以轻松的用函数递归写出代码,可是我们发现,当我们输入的值过大得不到我们想要的结果,这是为什么呢?
第一种情况:int所能容纳的范围有限,超出了int容纳的范围哦。
第二种情况:栈溢出。参数比较大,报错:stack overflow。系统分配给程序的栈空间是有限的,但是如果出现了死循环,或者(死递归),这样有可能导致一直开辟栈空间,最终产生栈空间耗尽的情况,这种现象我们称为栈溢出。(栈空间大小我们可以修改)。
那我们应该怎样去解决栈溢出的问题呢?把函数递归转化成函数迭代(循环)来实现题目要求
#include<stdio.h> int Fac(int i) { int j = 0; int r = 1; for (j = 1; j <= i; j++) { r = r * j; } return r; } int main() { int i = 0; scanf("%d", &i); int ret = Fac(i); printf("%d\n", ret); return 0; }
//错误点❌ int Fac(int i) { int j = 0; for (j = 1; j < i; j++)//i会变 { i = i * j; } return i; } //i会改变不能实现阶乘 //所以不要把输入值当作变量去使用 //输入值是循环限制条件即可
我们解决了栈溢出的问题,但超出int所容纳范围的问题都存在!
练习NO2.
//求第n个斐波那契数。(不考虑溢出) 斐波那契数列(Fibonacci sequence),又称黄金分割数列, 因数学家莱昂纳多·斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入, 故又称“兔子数列”,其数值为:1、1、2、3、5、8、13、21、34……在数学上,(前两个数相加等于第三个数) 这一数列以如下递推的方法定义:F(0)=1,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)。
#include<stdio.h> int Fib(int n) { if (n <= 2) return 1; else return Fib(n - 2) + Fib(n - 1); } int main() { int n = 0; scanf("%d", &n); int ret = Fib(n); printf("%d", ret); return 0; }
但是当数字过大,例如50,计算一直在持续,效率很低,为什么呢?
因为有大量重复的计算。
尽管计算效率很差,但是为什么没有溢出。因为一边递推一边回归,所以栈一边创建一边销毁。
接下来我们还是采用迭代(循环)来解决效率问题
#include<stdio.h> int Fib(int n) { int a = 1; int b = 1; int c = 1;//n<=2 c等于1 while (n > 2) { c = a + b; a = b; b = c; n--;//循环n-2次相当于相加的次数 } return c; } int main() { int n = 0; scanf("%d", &n); int ret = Fib(n); printf("%d", ret); return 0; }
如果使用递归很容易想到,写出来的代码没有明显的缺陷,那就可以使用递归。但是如果写出来的递归代码,有明显缺陷,例如:效率低下,栈溢出等等。我们可以转化成迭代的方式去解决问题。
总结
思考经典问题
大家可以思考一下,我们将在下次文章中,讲到这两个问题!!!
✔✔✔✔✔✔感谢大家的阅读,欢迎指正错误与不足。
代码----------------→【 gitee: https://gitee.com/TSQXG】
联系----------------→【邮箱:2784139418@qq.com】