1、递归的介绍
递归是一种解决问题的方法,在C语言中,递归就是函数自己调用自己的方法。
通过自己调用自己,递归可以将某个复杂的问题,分解成规模较小的子问题。
递归设置属于逆向思维,而且函数在不停的调用自己,换句话说是一层一层的嵌套
递归的核心思想:大事化小。
#include <stdio.g>
int main()
{
printf("haha\n");
main();
return 0;
}
以上的代码,就是一个简单的递归程序,不过上面的递归只是为了演示递归的基本形式,不是为了解决问题,所以代码在运行时,会陷入死递归,导致栈溢出(Stack overflow)
1.1 递归的限制条件
递归在书写的时候,有2个必要条件:
①递归存在限制条件,当满足这个限制条件的时候,递归便不再继续。
②每次递归调用之后越来越节点这个限制条件
2、递归举例
2.1 举例1:求n的阶层(n!)
方法一:迭代法
#include <stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
int i = 0;
int result = 1;
for (i = 1; i <= n; i++)
{
result = result * i;
}
printf("%d", result);
}
以上问题,用迭代的方法可以轻松解决。先定义result变量,初始化为1,然后让i循环n次,并且每次让result乘以i就可以了,最后result便是n!的结果
迭代法的思维方式:为了计算n!,我们是先从较小的数字开始计算的,比如:1!=1、2!=1!*2=2、3!=2!*3=6,以此类推。便可以计算出4!,5!,一直到n!。换句话说,我们在设计这个“迭代”算法的时候使用了“正向思维”的方式(已知---->未知)。它是从已知到未知的推导。递归的思维方式刚好相反,它属于“逆向思维”是从未知到已知的探索。
方法二:递归法
#include <stdio.h>
//递归函数定义
int function(int n)
{
//基础情况处理
while (n>=0)
{
if (n == 0)
return 1;
else
return function(n - 1) * n;//递归调用
}
}
int main()
{
int n = 0;
scanf("%d", &n);
int reslut = function(n);//递推到当前层
printf("%d", reslut);
return 0;
}
递归的思维方式:为了计算5!,我们从计算好了的4!,然后在4!的结果上乘以5便是5!。但是4!不知道,因此又需要求3!的结果,在3!的结果上乘以4便是4!。这样一直往前推导,便推到0!。0!=1,这样1!=1,2!=2,3!=6,4!=24,5!=120。这就是递归的逆向思维方式。
即从最终想要的答案出发,逐步向前寻找上一层的答案,并且用他们构造当前层的答案,直到找到最深的那一层,问题的答案足够简单,递归执行便开始返回,并将每层的答案一次填上。
1.2 举例2:计算斐波那契的第n项
方法一:迭代法
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", c);
}
我们知道斐波那契的前2个数都是1,然后前2个数相加就是第3个数,那么我们从前往后,从小到大计算就行。
方法2:递归法
int function(int n)
{
while (n)
{
if (n <= 2)
return 1;
else
return function(n - 1) + function(n - 2);
}
}
int main()
{
int n = 0;
scanf("%d", &n);
int result = function(n);
printf("%d", result);
}
递归属于“逆向思维”,我们希望从最终想要的答案出发,逐步向前寻找上一层的答案,并且用他们构造当前层的答案,比如我们要计算F[4],由于F[4]的计算需要F[3]和F[2],所以我们要调用递归函数,希望能够求得F[2]和F[3],在递归调用F[2]的时候,它又需要递归的调用F[0]和F[1],由于F[0]和F[1]是基础情况,可以直接得到答案,将他们相加就得到F[2]的值。以此类推,就可以成功得到F[4]的值。