👑个人主页:啊Q闻
🎇收录专栏:《C语言》
🎉道阻且长,行则将至
前言
函数递归是一种很好的编程技巧,能够很简便并且巧妙的解决一些编程问题。
一.初识递归
1.1概念
递归是函数自己调用自己,也是函数调用的一种。函数递归的思考方式就是把大事化小的过程,其中递归中的递就是递推的意思,归就是回归的意思,我们在接下来的代码中慢慢体会。
1.2限制条件
递归在书写的时候,有两个限制条件:
1.递归存在限制条件,当满足这个限制条件的时候,递归便不再继续。
2.每次递归调用后,会越来越接近这个限制条件
因此,我们在写代码时一定要满足这两个条件。
二.递归举例
题目:求n的阶乘(不考虑溢出)
思考:将一个较大的问题转化成一个与原问题相似的规模较小的问题来解决。
可以得到阶乘公式:(一般递归解决问题都要找出公式)
代码实现:
#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\n", ret);
return 0;
}
具体过程如下:
题目:输入一个整数m,按照顺序打印整数的每一位
比如:
输入:3456
输出:3 4 5 6
思考:3456%10可以得到最低位,3456/10可以去掉最低位。所以我们肯定要用这两个操作符实现代码。
代码实现:
#include<stdio.h>
void Print(int m)
{
if (m > 9)//只要是两位数即以上,就会进入循环 1. 递归存在限制条件,当满足这个限制条件的时候,递归便不再继续。
{
Print(m / 10); //2.每次递归调用后,会越来越接近这个限制条件
}
printf("%d ", m % 10);
}
int main()
{
int m = 0;
scanf("%d", &m);
Print(m);
return 0;
}
具体过程如下:
注意:每次函数调用时,都会为自己的m单独存储一份,从而在题目中递归调用的时候,不会改变每个递归中存放的m的值。
三.递归的缺陷
递归虽然好用,但是递归每次申请的空间都是等到回归的时候才开始释放,所以当递归层次太深时,就会浪费许多的空间,也可能导致栈溢出。
举个例子:求第n个斐波拉契数
思考:写出式子:
代码如下:
#include<stdio.h> int Fib(int n) { if (n < 2) { return 1; } else { return Fib(n - 1) + Fib(n - 2); } } int main() { int n = 0; scanf("%d", &n); int ret = Fib(n); printf("%d\n", ret); return 0; }
我们会发现计算机很难算出50的值,这是因为代码运行时进行了大量的重复运算
我们写个代码证明一下:
#include<stdio.h> int count = 0; int Fib(int n) { if (n == 3) { count++;//利用count计算求某个数时3出现的次数 } if (n < 2) { return 1; } else { return Fib(n - 1) + Fib(n - 2); } } int main() { int n = 0; scanf("%d", &n); int ret = Fib(n); printf("%d\n", ret); printf("count=%d\n", count); return 0; }
会发现,count是一个很大的值
但是该题如果用迭代效率会高出许多,代码如下:
#include<stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
int a = 1;
int b = 1;
int c = 1;
while (n > 2)
{
c = a + b;
a = b;
b = c;
n--;
}
printf("%d\n", c);
return 0;
}
所以,递归虽然好用,但是也会带来许多问题
文章到这里结束哦,谢谢大家阅读,如果对你有用的话,就三连支持一下吧。