目录
- 什么是递归
- 递归的限制条件
- 递归的举例
- 递归与迭代
- 扩展学习
1.什么是递归
1.1递归的含义
在C语言中,递归就是函数自己调用自己。
什么意思呢?接下来我将写一段代码展示
例一:
1.2递归的思想
递归,顾名思义便是递推,回归,把⼀个⼤型复杂问题层层转化为⼀个与原问题相似,但规模较小的⼦问题来求解;直到子问题不能再被拆分,递归就结束了。
以上面的代码为例
2.递归的限制条件
先给大家看看世界上最简单的递归
看到此段代码后,我们会发现一直是函数自己调用自己,而且一直死循环下去导致死递归,从而导致栈溢出(先不做过多了解)
因此,使用递归的时候我们有必要限制一些条件
递归在书写的时候,有2个必要条件:
• 递归存在限制条件,当满足这个限制条件的时候,递归便不再继续。
• 每次递归调用之后越来越接近这个限制条件。
3. 递归的举例
例2:
题目要求:求n的阶乘
看到此题目后,我们知道n!= n * (n-1)!
仔细一看我们是不是把n的阶乘分成了两个子问题,那么继续把(n-1)!分成(n-1)*(n-2)!
如此循环下去,我们会发现这其实便是递归。清楚目的后,便有了如下代码
#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 r = Fact(n);
printf("%d的阶乘为%d", n, r);
return 0;
明白递归的思想和看了例一的形象图我们也可以自己分析此段代码的递归
例3:
题目要求:输⼊⼀个整数m,按照顺序打印整数的每⼀位。
这题也是利用了递归的思想:
首先假设我们输入1234,那么按照题目要求便是打印1 2 3 4。
1234拆成
(123)+ 4
(12)+ 3 + 4
(1)+ 2 + 3 + 4
明白方法后,写出此代码就相当容易了
#include<stdio.h>
Print(int n)
{
if (n > 9)
Print(n / 10);
printf("%d ", n % 10);
}
int main()
{
int n = 0;
scanf("%d", &n);
Print(n);
return 0;
}
例4:
题目要求:求第n个斐波那契数
首先得明白斐波那契数是什么
1,1,2,3,5,8,13……
数列{an},{a1}=1,{a2}=1,{a3}=2,a(n+2)=a(n+1)+a(n) (n属于正整数)
这道题自己用递归的思想解
#include<stdio.h>
int Fit(int a)
{
if (a <= 2)
return 1;
else
return Fit(a - 1) + Fit(a - 2);
}
int main()
{
int a = 0;
scanf("%d", &a);
int r = Fit(a);
printf("%d", r);
return 0;
}
4.递归与迭代
以上段代码为例,如果我们要求第50个斐波那契数列,是否可以实现呢?
输入50后我们发现竟然没弹出对应的数值,由此我们是否可以怀疑计算机是不是在偷懒呢?当然不是
打开后端管理器可以发现计算机一直在计算,只是需要很长时间才能算出结果,这个计算所花费的时间,是我们很难接受的,这也说明递归的写法是非常低效的。
那么,是否有更有效的方式解决呢?答案是肯定的
我们可以使用迭代的方式进行优化
思路:假设要求第5个斐波那契数,创建三个变量,第一个斐波那契数为1赋予变量a,接着第二个斐波那契是2赋予变量b,第三个变量就为a+b的值,然后第5个斐波那契数自减1,如此循环下去,就会得出想要的值
5.扩展学习
5.1青蛙跳台阶问题
题目要求:一只青蛙,一次可以跳一个台阶,也可以跳2个台阶
问:这只青蛙,跳到第n个台阶,有多少种跳法?
我们仔细思考,这题是不是和斐波那契数列是一样的
5.2汉诺塔问题
另一章节会讲到。