如果一个函数直接或间接地调用自身,他就被称为递归函数。在C中,所有的函数都可以进行递归调用。
例子:
#include<stdio.h>
int main(void) {
printf(" The universe is never ending!!");
main();
return 0;}
下面是递归函数的另一个例子。它是算前n个整数值得和:
int sum(int n)
{
if(n<=1)
return n;
else
return(n+sum(n-1));
}
从上例可知,简单的递归函数遵循一种标准模式。一般情况下,存在一个基本条件(或多个基本条件)。在进入递归函数时,首先测试这个基本条件。如果满足基本条件,递归过程便告结束。然后便是通用的递归条件,其中一个变量(通常是个整数)作为函数的参数,它最终能够到达基本条件。
在sum()中,变量n每次减1,直到符合n等于1的这个基本条件。
例子:n的阶乘(n!=n((n-1)!)
(递归函数)
int factorial(int n)
{
if(n<=1)
return 1;
else
return (n*factorial(n-1));
}
调用递归函数,在返回到最初的调用之前,递归过程将会激活n层嵌套的函数调用。这意味完成这个计算要n个函数调用。
为了提高效率,绝大多数的简单的递归函数可以很方便的写成迭代函数。
例子:(迭代函数)
int factorial(int n)
{
int product=1;
for(;n>1;--n)
product*=n;
return product;
}
下一个例子是用于字符操作的递归函数,它可以很方便的改写成迭代函数。作用是吧输入文本倒着打印出来。
#include<stdio.h>
void wrt_it(void);
int main(void) {
printf("Input a line:");
wrt_it();
printf("
");
getchar();
return 0;
}
void wrt_it(void)
{
int c;
if((c=getchar())!='
')
wrt_it();
putchar(c);
}
一般情况下,递归看上去显得更为优雅,完成相同计算所需要的变量更少。递归通过把每个函数调用的参数和变量压入到堆栈中来支持它的实现。这种队参数和变量的压栈虽然对用户不可见,但仍然需要消耗时间和空间。在有些机器上,一个只接受1个整数参数的简单递归函数可能需要堆栈中8个32位字的空间。
下个例子我们讨论与Fibonacci数列相关的效率问题。(0,1,1,2,3,5,8,13,21…)
int fibonacci(int n)
{
if(n<=1)
return n;
else
return(fibonacci(n-1)+fibonacci(n-2));
}
尽管使用递归很有诱惑力,但必须注意它的运行时限制和低效率。有时候,我们不得不摒弃递归方案,改用等价的迭代方案。
递归效率不高,也许就不应该使用了,但是,这种低效率造成的后果往往并不严重,对于许多应用程序来说,递归代码容易编写、理解和维护。
例子:汉诺塔(Hanoi)
#include<stdio.h>
#include<string.h>
void hanoi(int n,int a,int b,int c);
int main(void) {
int n;
for(;1==1;){
printf("Input n:");
scanf("%d",&n);
hanoi(n,1,2,3);
}
getchar();
return 0;
}
void hanoi(int n,int a,int b,int c){
if(n==1){
printf("%d->%d
",a,c);
}
else
{
hanoi(n-1,a,c,b);
printf("%d->%d
",a,c);
hanoi(n-1,b,a,c);
}
}