C语言的一个最大的特点就是允许函数的递归调用。递归调用指的是:在一个函数的调用过程中又出现直接或者间接地调用该函数本身,称为函数的递归调用。
首先来看一个比较经典的例题:
有五个学生在一起,问第五个学生多大,他说比第四个学生大两岁,问第四个学生,他说他比第三个学生大两岁,问第三个学生,他说他比第二个学生大两岁,问第二个学生,他说他比第一个学生大两岁。最后问第一个学生,他说他10岁。请问第五个学生多大?
解题思路:
要求的是第五个学生的年龄,而第五个学生的年龄又取决于第四个学生的年龄,第四个学生的年龄又取决于第三个学生的年龄,依此类推。我们可以设计一个函数Age,用来计算第n个学生的年龄。由此可知:
Age(5):表示第5个人的年龄;
Age(4):表示第4个人的年龄;
Age(3):第3个人的年龄;
Age(n):第n个人的年龄;
Age(n-1):第n-1个人的年龄。
由此可以得出以下的表达式:
Age(5)=Age(4)+2
Age(4)=Age(3)+2
Age(3)=Age(2)+2
Age(2)=Age(1)=2
Age(1)=10
转换为数学表达式就是:
Age(n)=10;//n=1
Age(n)=Age(n-1)+2;//n>1
由此我们可以写出如下的代码:
int Age(int n)
{
int tmp;
if(n == 1){
return 10;
}
else
tmp=Age(n-1)+2;
return tmp;
}
函数在执行的时候 ,调用了本身,使用了第Age(n-1)的返回值,经过多次的调用,直到最后一次n=1,停止调用。再依次返回上层的函数,求第n个学生的年龄。这样说可能有点的模糊,看了下面的图,你就会明白函数的递归调用时的函数执行情况。
图①
函数调用执行图
图②
函数执行时存储示意图
这两张图片形象的描述了函数的执行情况。最左边的是我们之前写的代码,左边的图示形象的描述了函数在执行过程中函数的调用以及执行过程.首先,图一表示的是函数的调用执行图,函数在运行的时候,首先执行主函数等到需要调用Age函数的时候,停下来,又去执行Age函数,从上往下执行的时候遇到Age(5),又因为函数的数据存储是按照栈的数据结构进行存放的,所以运行到需要调用Age(4)的时候,将未执行完的函数暂时先进行入栈的操作,存放在栈里面,接着去执行Age(4),等到需要执行Age(3)的时候,又将Age(4)入栈,依此类推,直到执行到Age(1)的时候,判断if语句里面成立的时候,返回10,将返回的值返回给Age(2),然后Age(1)出栈,让Age(2)去执行未完成的操作,依此类推,直到执行到Age(5),这时候栈全空,直到运行到主函数返回tmp的值18给主函数。到这里,所有的递归都已经执行完了。