1. 什么是递归
递归其实是一种解决问题的方法,在C语言中,递归就是函数自己调用自己。
简单的递归代码:
int main()
{
printf("hehe\n");
main(); //main 函数中又调用了main函数
return 0;
}
代码最终会陷入死循环,导致栈溢出。
递归的思想:
把一个大型复杂问题层层化为一个与原问题相似,但规模较小的子问题来求解;直到子问题不能被拆分,递归就结束了。所以递归的思考方式就是把大事化了的过程。
递归中的递就是递推的意思,归就是回归的意思
2. 递归的限制条件
在递归书写的时候,有2个必要条件:
- 递归存在限制条件,当满足这个限制条件的时候,递归便不再继续。
- 每次递归调用之后越来越接近这个限制条件
3. 递归的举例
求n的阶乘
举例:
5! = 5*4*3*2*1
4! = 4*3*2*1
所以:5! = 5 * 4!
print(int a)
{
if (a <= 0)
{
return 1;
}
else {
return a * print(a - 1);
}
}
int main()
{
int a = 0;
scanf("%d", &a);
int ret = print(a);
printf("%d", ret);
return 0;
}
分析:
当a<=1时,a的阶乘是1,其余a的阶乘都是可以通过上述公式计算。
a的阶乘的递归公式如下:
顺序打印⼀个整数的每⼀位
输入一个整数m,打印这个按照顺序打印整数的每一位。
输入:1234 输出:1 2 3 4
输入:520 输出:5 2 0
void value(int n)
{
if (n > 9)
{
value(n / 10);
}
printf("%d ", n % 10);
}
int main()
{
int n = 0;
scanf("%d", &n);
value(n);
return 0;
}
分析:
value(n)
如果n为1314,那表示为
value(1314) //打印1314的每一位其中1314中的4可通过%10得到,那么
value(1314)可分为两步:
1.value(1314 / 10) //打印131的每一位
2.value(1234 % 10) //打印4
完成上述两步,那就完成了1314每一位的打印
那么value(1314)又可拆为value(1314 / 10) + value(1314 % 10)
直到被打印的数字变成⼀位数的时候,就不需要再拆分,递归结束。
4. 递归与迭代
递归
递归是一种很好地编程技巧,但是很多技巧一样,也是可能被误用的,就像举例1一样的,看到推导公式,很容易就被写成递归的形式:
int Fact(int n)
{
if (n <= 0)
return 1;
else
return n * Fact(n - 1);
}
在C怨言中每一次函数调用,都需要本次函数调用在栈区申请一块内存空间来保存函数调用期间的各种局部变量的值
这块空间被称为运行时的堆栈,或者函数栈帧。
函数不返回,函数对应的栈帧空间就⼀直占⽤,所以如果函数调⽤中存在递归调⽤的话
每⼀次递归函数调⽤都会开辟属于⾃⼰的栈帧空间,直到函数递归不再继续,开始回归,才逐层释放栈帧空间。
所以如果采⽤函数递归的⽅式完成代码,递归层次太深,就会浪费太多的栈帧空间,也可能引起栈溢出的问题。
求第n个斐波那契数
分析:
斐波那契数列指的是这样的一个数列:
1,1,2,3,5,8,13,21,34,55 …
这个数列从第三项开始,每一项都等于前两项之和
代码
#define _CRT_SECURE_NO_WARNINGS 1
#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", ret);
return 0;
}
当我们n输入为60的时候,需要很长的时间才能算出结果,说明了这个递归的写法是非常低效的。
其实递归程序会不断的展开,在展开的过程中,我们很容易发现,在递归的过程中会有重复计算,而且递归层次越深,冗余计算就会越多。
迭代
int Fib(int n)
{
int a = 1;
int b = 1;
int c = 1;
while (n > 2)
{
c = a + b;
a = b;
b = c;
n--;
}
return c;
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = Fib(n);
printf("%d", ret);
return 0;
}
这样效率会高出不少