一.递归的概念及应用条件
首先说一下什么是递归,递归其实就是一个函数在它的函数体内调用它自身。
但是递归是有条件的,先用一个代码展示一下什么是递归
#include<stdio.h>
int main()
{
printf("hehe");
main();
return 0;
}
这就是一个非常简单的递归,正如概念所说,递归就是在一个函数中调用自身,而这个递归可以实现吗?答案很明显是不可以的,这个递归没有一个运行的条件递归无法停止,则会不断进行不会停止,最后则会导致栈区堆溢。
既然这样那么递归的实现需要什么条件呢?
1.纯在限制条件,当满足这个限制条件时递归便不再继续。
2.每次递归调用之后越来越接近这个目标。
那么根据这两个条件去修改这个上面这段代码就是
#include<stdio.h>
int main()
{
int n=4;
if(--n)
{
printf("hehe");
main();
}
return 0;
}
这样的一个代码就有了一个运行的条件当 n--到0时为假,if便不再进行,再依次释放函数,这就是比较简单的一个递归。当然这段代码是没有实际意义的。
那既然如此,是不是满足这两个条件时就一定可以实现呢?那我们不妨看一下这个代码
#include<stdio.h>
void print(int n)
{
if (--n)
{
printf("hehe");
print(n);
}
}
int main()
{
int n = 10000;
print(n);
return 0;
}
这个函数是不是上面所说的两个条件都满足啊,那这个代码真的可以如我们所说可以正常的跑起来呢,如果我们运行一下不难发现,这个代码刚开始会死循环但是一会之后就会跳出,这是为什么呢?我们f10调试一下看看
出现了这样的情况,这原因也是很简单。
其实函数每一次调用都会向内存栈区上申请一块空间。这一块空间主要是用来存放函数中的局部变量和函数调用过程中的上下文的信息。
而这一块空间一般叫函数的运行时堆栈,也叫函数栈帧空间。编译时会自动根据需要开辟空间。
所以说当函数调用次数过多时会导致堆栈使栈区溢出而不能完全实现代码中的内容。
二.递归的使用
介绍了递归的概念还有递归的使用条件我们下面来实现递归的一些应用吧,下面一段代码我我用递归的形式来实现my——strlen函数
#include<stdio.h>
int my_strlen(char* p)
{
if (*p != '\0')
{
return 1 + my_strlen(p+1);
}
else
{
return 0;
}
}
int main()
{
int ret = 0;
char arr[] = "welcome to my world";
ret =my_strlen(arr);
printf("%d\n", ret);
return 0;
}
下面我再迭代的方式给大家实现一下my——strlen的实现大家来对比一下。
#include<stdio.h>
int my_strlen(char arr[])
{
int count = 0;
int i = 0;
while (arr[i] != '\0')
{
count++;
i++;
}
return count;
}
int main()
{
char arr[] = "welcome to my world";
int ret=my_strlen(arr);
printf("%d", ret);
return 0;
}
有可能这个函数看起来不是特别明显,其实使用递归的方法一般代码比较简短,递归的特点就是用少量的代码来完成复杂的过程。
三 .运用递归实现斐波纳契数的打印
斐波纳契数就是前两个数相加等于后两个数的一些列数如:
1,1,2,3,5,8,13.......55
0,1,2,3,4,5,6.........10
那么如何用递归的方法去实现这样的一系列数字呢,下面来给大家展示一下:
#include<stdio.h>
int Fei(int n)
{
if (n <= 2)
{
return 1;
}
else
{
return Fei(n - 1) + Fei(n - 2);
}
}
int main()
{
int n = 0;
int ret = 0;
scanf("%d", &n);
ret = Fei(n);
printf("%d\n", ret);
return 0;
}
是不是很简单,那他真的可以实现我们输出任意位的斐波纳契数吗?在我们的电脑上打印一下不难发现我们当数字比较小的时候打印的速度很快但当数字比较大时打印的速度会变慢。当我们在Fei函数中加入一段代码
#include<stdio.h>
int Fei(int n)
{
if (n == 3)
{
printf("666\n");
}
if (n <= 2)
{
return 1;
}
else
{
return Fei(n - 1) + Fei(n - 2);
}
}
int main()
{
int n = 0;
int ret = 0;
scanf("%d", &n);
ret = Fei(n);
printf("%d\n", ret);
return 0;
}
这时我们发现打出了很多的“666”这就说明n=3这个过程都经历了好多遍,这就说明并不是所有的问腿都适合我们的递归,那下面我们用非递归的方式再给大家演示一下吧
#include<stdio.h>
int Fei(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;
int ret = 0;
scanf("%d", &n);
ret = Fei(n);
printf("%d\n", ret);
return 0;
}
这就是我们非递归的方式了,这样当输入比较大的数字的时候依然可以很快的打印出来。
四.结尾小结
好了这就是我们的递归了使用递归记住两个点就可以了:从复杂到简单的问题,并且有限定条件并且在递归的过程中是逐渐接近这个条件的,就可以使用递归。
一些1问题我们使用递归可以很快的解决,但有些问题不是特别适合递归,总而言之言而总之,递归还是非常好用的!!
拜拜啦!!!!!
下期预告:
1.汉诺塔问题
2.青蛙跳台阶问题