前言:函数递归是一个比较抽象的部分,但在C语言中用的也比较多,今天我来分享一下关于函数递归的知识.
1. 递归的含义
很多同志看到递归这个词会有点懵
其实,递归是一种与嵌套类似的解决问题的方法
在C语言中
递归就是 函数自己调用自己
即递推+回归
在此,我给出一个最简单的C语言递归
#include <stdio.h> int main() { printf("love\n"); main(); //调用main函数 return 0; }上面代码在打印完 "love" 后,再次调用main函数,接着又打印 "love",进入无限循环
我用一种方式来更加清楚了解一下 函数递归
当然,从实际意义考虑的话,上面代码是无意义的
2.递归的意义
递归,可以让一个复杂的问题,拆分成一小块一小块,直到小问题不再能拆分
接下来,请大家慢慢体会
3.递归的限制条件
递归书写的时候需要写限制条件
— 如果递归时满足这个限制条件,递归将不再进行
— 随着递归的进行将越来越接近这个限制条件
4.递归举例
求n的阶乘
n的阶乘:1*2*3*...(n-1)*n
例如:
假设n是4,那么n的阶乘就是 4*3*2*1
即 4!=4*3*2*1
加入递归思想,这道题将变成一个一个规模较小的式子(n>1)
直到 n 等于 1或时,不再拆解
接下来,我们实际操作一下
#include <stdio.h> int Fact(int n) { if (n <= 0) return 1; else return n * Fact(n - 1); //在这里开始递归 } int main() { int n = 0; scanf("%d", &n); int ret = Fact(n); printf("%d", ret); return 0; }运行结果
我们用图画推导一遍
5.递归的弊端
递归是一个很好的解决问题的方法,但是像其他方法一样,有很多时候我们容易去误用它,这时候我们就得用循环来解决了
例如:
求第n个斐波那契数
这是一个极端的例子,能充分反映递归的弊端
斐波那契数列:1 1 2 3 5 8 13 ...
第n个斐波那契数:F(n)= F(n-2)+F(n-1) → n>2
F(n)= 1 → n<=2
递归斐波那契
假如我们把斐波那契写成递归的形式,如下:
int F(int n) { if (n <= 2) return 1; else return F(n - 1) + F(n - 2); } int main() { int n = 0; scanf("%d", &n); int r = F(n); printf("%d\n", r); return 0; }也许当你求第小于50位的斐波那契数的时候,发现没问题,而且很对
但是当你输入第50位或50位往后的时候,发现程序加载不出来结果
这是为什么呢?
我们不妨画个图
我们可以看到,随着递归的不断深入,有许多重复的计算,而且递归次数指数增加,导致程序计算量大,效率低
循环斐波那契
而当我们用循环解决第n个斐波那契数时,我们会发现,计算量少了很多很多
我们尝试写一下循环
斐波那契数前两位数为1,1
我们可以实现(n>=3)
仔细思考,我们会发现,计算第n个斐波那契数只需要计算n-2次
int F(int n) { int a = 1; int b = 1; int c = 1; //n是1,2时,不会进入循环,直接打印1 while (n >= 3) { c = a + b; a = b; b = c; n--; } return c; } int main() { int n = 0; scanf("%d", &n); int r = F(n); printf("%d\n", r); return 0; }当我们输入50时,我们发现计算速度很快,但是是个负数?
这是因为,整型变量是有范围的,超出范围会随机报数(就像许多类型变量都是有范围的)
但是你会发现,计算很快很快,甚至如果你输入50000,速度也是很快(虽然结果依然是错的)
6.递推的选择
在未来解决问题时,如果使用递归非常容易,并且写出的代码也没问题,那就使用递归
但如果使用递归有明显缺陷,那就不能使用递归,需要考虑其它方法:迭代(循环是迭代的一种)
总结:函数递归固然能很好的解决问题,但是问题千千万,总有一些刁钻的问题不能使用递归,还容易让我们陷进去.
所以,不仅仅是这一块,整个C语言包括其它编程语言,在解决实际问题时,都不能单一的只思考一个方法,而是运用它们各自优势,互相配合着解决问题.
作者留言:本人是初学者,制作不易,如有错误和不恰当的地方,欢迎指出和分享建议
制作时间:2023.12.8









1321

被折叠的 条评论
为什么被折叠?



