一、什么是递归
所谓递归,简单点来说,就是一个函数直接或间接调用自身的一种方法,每调用一次就进入新的一层。它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。递归函数必须有结束条件。当函数在一直递推,直到遇到结束条件后返回,所以递归要有两个要素,结束条件与递推关系
二、递归的简单应用
第一个人的年龄为十岁,第二个人的年龄比第一个人年龄大两岁,以此类推,求第五个人的年龄;
#include <stdio.h>
int Age(int n)
{
if(n==1)//第一个人的年龄
{
return 10;
}
else
{
return Age(n-1)+2;//递归过程,自己调用自己,终止条件n=1
}
}
int main()
{
printf("%d\n",Age(5));
return 0;
}
三、递归与栈的关系
递归在栈上开辟空间,栈的空间大约1M左右。
常常听到 “递归的过程就是出入栈的过程”,这句话怎么理解?我们以上述代码为例,取 n=5,则过程如下:
- 当n=5时,
Age(5)
调用了Age(4)
,Age(4)
又接着调用Age(3)
,Age(3)
又接着调用Age(2),Age(2)
又接着调用Age(1),
直到遇到Age(1)结束
,这个过程都是入栈; - 因 1 是递归结束条件,故不再入栈,此时栈高度为5,也就是所谓的递归深度;
- Age(1)做完,出栈,而Age(1)做完意味着Age(2)也做完,同样进行出栈,重复下去,直到所有的都出栈完毕,递归结束。
如下图:
四、递归总结
1、当函数自己调用自己时,系统将自动把函数中当前的变量和形参暂时保留起来,在新一轮的调用过程中,系统为新调用的函数所用到的变量和形参开辟另外的存 储单元(内存空间)。每次调用函数所使用的变量在不同的内存空间。
2、递归调用的层次越多,同名变量的占用的存储单元也就越多。一定要记住,每次函数的调用,系统都会为该函数的变量开辟新的内存空间。
3、当本次调用的函数运行结束时,系统将释放本次调用时所占用的内存空间。程序的流程返回到上一层的调用点,同时取得当初进入该层时,函数中的变量和形参 所占用的内存空间的数据。
4、所有递归问题都可以用非递归的方法来解决,但对于一些比较复杂的递归问题用非递归的方法往往使程序变得十分复杂难以读懂,而函数的递归调用在解决这类 问题时能使程序简洁明了有较好的可读性;但由于递归调用过程中,系统要为每一层调用中的变量开辟内存空间、要记住每一层调用后的返回点、要增加许多额外的 开销,因此函数的递归调用通常会降低程序的运行效率。
递归的优点:代码简洁,可读性高。
递归的缺点:一般情况下空间复杂度较高,运行效率降低。