目录
递归
递归顾名思义就是:自己调用自己
我们先来看看递归错误示范
代码如下(示例):
#include<stdio.h>
int main()
{
printf("hehe\n");
main();
return 0;
}
main函数无限制的调用,无限循环下去,导致栈溢出
Stack overflow : 栈溢出
一、递归
1.思想
大型复杂问题转化为相似问题,就是大事化小
递:递推 归:回归
2.限制条件
- 递归存在限制条件,当满足,则不继续
- 每次递归接近这个条件
二、举例
1.求n的阶乘(1~n)的累积(不考虑栈溢出)
n ! = n (n-1) ! :5!=5*4*3*2*1
代码如下(示例):
#include<stdio.h>
//数字不能太大
int fact(int n)//n>=0
{
if (n == 0)
{
return 1;
}
else
{
return n * fact(n - 1);
}
}
int main()
{
int n = 0;
scanf("%d", &n);
int r=fact(n);
printf("%d",r);
return 0;
}
上段代码就是使用了递归的思想来实现的(1~n)!的阶乘
结果展示:
缺点:输入的数字不能太大,容易栈溢出
下面用画图来理解其中的思想
递归思想
编译器编译的实现
编译器实现的粗略图可以让我们更容易理解递归是如何分配的
2.顺序打印一个整数的每一位
先用递归的思想来实现
如下图所示:
我们可以看出只要每次去%10就得到最后一位,/10就减少一位,所以我们就只要循环的%10和/10就可以得到每一位
代码如下(示例):
#include<stdio.h>
void Print(int n)//n>=0
{
if (n > 9)//递归停下的条件
Print(n / 10);
printf("%d ", n%10);
}
int main()
{
int n = 0;
scanf("%d", &n);
Print(n);
return 0;
}
结果展示:
这里我们再不知道递归时,就会不按顺序打印。
递归实现思想
三、递归与迭代
递归:运行时开销——浪费空间
迭代:效率高
如何选择递归还是迭代?(看情况)
- 如果说一个问题使用递归去写的时候,写起来简单,并且写出来没有明显问题就使用递归
- 如果使用递归存在明显的问题,那就得想办法写成迭代的方式。
举例:求第n个斐波那契数
定义:1 1 2 3 5 8 11 21 34 55......
前两个数加起来等于第三个数
并且有一个公式
根据这个公式我们很容易写成递归
代码如下:
#include<stdio.h>
int fib(int n)
{
if (n == 3)
count++;
if (n <= 2)
return 1;
else
return fib(n - 1) + fib(n - 2);
}
int main()
{
int n = 0;
scanf("%d", &n);
int r = fib(n);
printf("%d", r);
return 0;
}
结果如下:
缺点:计算机很累,重复运算(并不意味栈溢出),效率低
所以我们要办法去用迭代的方式
代码如下:
#include<stdio.h>
int fib(int n)
{
int a = 1;
int b = 1;
int c = 1;
while (n >= 3)
{
c = a + b;
a =b;
b =c;
n--;
}
return c;
}
int main()
{
int n = 0;
scanf("%d", &n);
int r = fib(n);
printf("%d", r);
return 0;
}
总结
本篇主要是了解递归的思想,有了递归的思想后可以变成一种解决问题的方式,但是也要慎用。