一、递归调用的概念
C语言允许嵌套地调用函数,也就是说,在调用一个函数的过程中,又去调用另一个函数。当嵌套中被调用的函数是该函数本身时,这种情况就称之为函数的递归调用。例如:
int main()
{
…
tell_story(10);
return 0;
…
}
void tell_story(int n)
{
…
tell_story(n+1);
…
}
二、采用递归调用的条件
在解决实际问题时,能否用递归的方法来解决,取决于问题自身的特点。一个问题要用递归的方法来解决,需满足以下条件:
1.原问题可转化为一个新问题,而这个新问题与原问题有相同的解决方法。
2.新问题可继续这种转化,在转化过程中,问题有规律地递增或递减。
3. 在有限次转化后,问题得到解决,即具备递归结束的条件。
其实说白了最重要的就是两个因素,一是这个问题有一定的规律性,二是这个问题的规律要有边界。
所以我们采用递归调用来解决问题时,其实要做的就只有两件事情(我也称之为递归调用的套路),一是找到边界,if语句后面放边界,二是找到规律,else语句后面放规律。
三、递归调用的典型案例
1.斐波那契额数列问题
斐波那契额数列如下:
1、1、2、3、5、8、13、21、34…
斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入,故又称“兔子数列”。其数值为:1、1、2、3、5、8、13、21、34……在数学上,这一数列以如下递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n ≥ 3,n ∈ N*)。
斐波那契数列在自然界和日常生活中有许多应用。例如,在植物学中,一些植物的花瓣数量呈现斐波那契数列的模式;在建筑学中,一些建筑物的设计也利用了斐波那契数列来达到视觉上的美感;在艺术和音乐中,斐波那契数列也被用来创造和谐的效果。此外,斐波纳契数列在计算机科学中也有广泛的应用,例如在图形处理和算法设计中。
如果现要求某一项的值,用函数递归调用的方法来解决的思路如下:
1.边界:由斐波那契额数列的描述可知,第一项和第二项不满足一般规律,我们可以把第一项和第二项作为边界条件;
2.规律:除前两项外,其余每项均满足此规律 F(n)=F(n-1)+F(n-2)
代码如下:
#include<stdio.h>
int Fib(int n);
int main()
{
int N,F;
printf("请输入您要查找的项数:\n");
scanf("%d",&N);
F=Fib(N);
printf("斐波那契数列的第%d项的值是%d\n",N,F);
return 0;
}
int Fib(int n)
{
int f;
if(n==1||n==2)
{
f=1;
}
else
{
f=Fib(n-2)+Fib(n-1);
}
return f;
}
//举例:第5项的值递归调用过程分解fib(5)=fib(3)+fib(4)=fib(1)+fib(2)+fib(2)+fib(3)=fib(1)+fib(2)+fib(2)+fib(1)+fib(2)=5
2.猴子吃桃问题
猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个。第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上想再吃时,见只剩下一个桃子。求第一天共摘多少桃子。
按照题意,人工演算观察规律:
第10天:1个
第9天:(1+1)*2=4个
第8天:(4+1)*2=10个
第7天:(10+1)*2=22个
…
所以一般规律是:f=[F(N+1)+1]*2
如果现要求第一天摘的桃子数,用函数递归调用的方法来解决的思路如下:
1.边界:第十天剩下一个桃子;
2.规律:前一天的桃子数是后一天的桃子数加1再乘2:f=(eat_peach(day+1)+1)*2
代码如下:
#include<stdio.h>
int eat_peach(int day);
int main()
{
int n;
n=eat_peach(1);
printf("这只猴子第一天摘了%d个桃子\n",n);
return 0;
}
int eat_peach(int day)
{
int f;
if(day==10)
{
f=1;
}
else
{
f=(eat_peach(day+1)+1)*2;
}
return f;
}
3.阶乘问题
我们都知道n的阶乘为:n!=nx(n-1)x(n-2)x…x1
特殊情况为:1!=1,0!=1
所以,按照刚才的套路,边界和规律已经很明显了:
1.边界:1!=1,0!=1;
2.规律:但是规律还需要做一点变化,n!=nx(n-1)x(n-2)x…x1=nx(n-1)!
代码如下:
#include<stdio.h>
int Factorial(int n);
int main()
{
int F,N;
printf("请输入要求的阶乘:\n");
scanf("%d",&N);
F=Factorial(N);
printf("%d的阶乘是:%d\n",N,F);
return 0;
}
int Factorial(int n)
{
int f;
if(n==1||n==0)
{
f=1;
}
else
{
f=n*Factorial(n-1);
}
return f;
}
大家仔细观察就会发现以上代码的套路都一样,认真看看。