什么是递归?
在C语言中,函数递归就是函数自己调用自己。递归是一种解决问题的方法。
递归的和核心思想:大事化小,小事化了。
把大型的问题,转换成一个个与原问题相似,但是规模较小的子问题来解决,直到子问题不能再拆分递归就结束了。
递归的限制条件:1.递归有限制条件,满足这个条件的时候,递归不再继续。
2.每次递归都会越来越接近这个条件。
生活中最常见的,可以使用递归来解决的问题:求n的阶乘
求阶乘的公式:n ! = n * ( n - 1 )!
例如:求5的阶乘,5 != 5 * 4 * 3 * 2 * 1
也可以写成: 5 ! = 5 * 4 !
也可以写成: 5 ! = 5 * 4 * 3 !
也可以写成: 5 ! = 5 * 4 * 3 * 2!
也可以写成: 5 ! = 5 * 4 * 3 * 2 * 1!
可以参考这个图:
由此图可以看看出:
大问题是n的阶乘,即: n!
大问题拆分成小问题: n * (n - 1)!
再拆分成小问题: n * ( n - 1 ) * ( n - 2 )!
最后拆分到不能拆分: n * ( n - 1 ) * ( n - 2 ) * 。。。。。。2 * 1
拆分的这个过程就叫做 “递”
接下来就要 “归” 了
如图:从头“递”到尾,而“归”是从尾往头。
算出2!————>算出3!————>算出4!。。。。。。。算出(n-2)!————>算出(n-1)!
—————>进而得到n的阶乘
从头“递”到尾,从尾往头“归”,这就是递归的全过程。
代码的实现思路:
我们可以定义一个函数 Fuction() 用来实现相关的计算
n=0时,1是递推的终止
n>0时,函数还在计算
所以可以分为两个步骤:
两个分支,可以用if语句
Function部分完整代码:
int Function(int n)//形式参数
{
if (n == 0)
{
return 1;
}
else
{
return n * Function(n - 1);
}
}
main函数部分的完整代码:
int main()
{
int n = 0;
scanf("%d", &n);
int ret = Function(n);
printf("%d\n", ret);
return 0;
}
测试结果:
5的阶乘就是120,答案正确。
递归限制条件的重要作用:
限制条件不仅仅是判断一个问题能不能用“递归”的方法去解决,而且还是做题的关键。
我给出一个题目:拆分数字
能否用递归的方法解决?
假如要拆分123
123%10=3 123/10=12
12%10=2 12/10=1
1%10=1
由此可以看出 ,最后1<10的时候,就没办法计算下去了,也就相当于说,<10的数没办法再进行计算了。必须是10以上的数,也就是>9的数才能计算。
因此,满足<10的时候,递归结束,而且每次进行计算这个数都会越来越接近10。
因此,这个问题满足使用递归的要求,能够使用递归来解决
一样的,定义一个函数Function用来计算
void Function(int n)
{
if (n > 9)
{
Function(n / 10); //123 / 10 = 12
}
printf("%d ", n % 10); //123 % 10 = 3
}
main函数部分:
int main()
{
int n = 0;
scanf("%d", &n);
Function(n);
return 0;
}
测试结果:
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
最终测试:求第n个斐波那契数
什么是斐波那契数列?
斐波那契数列是指这样一个数列:0,1,1,2,3,5,8,13,21,34,55,89……这个数列从第3项开始 ,每一项都等于前两项之和
思考
它是否能用递归?就看它满不满足两个限制条件
设第n个斐波那契数是Fib(n)
斐波那契数列公式:Fib(n) = Fib(n-1)+Fib(n-2)
我们发现,递推到Fib(1)就结束递推,而且每一次递推都接近Fib(1),满足了使用递归的两个条件
定义一个Fib函数用来计算。
以Fib(1) = 1作为数列的开始,那么 Fib(0) = 0,这样方便计算
int Fib(int n)
{
if (n == 0)
{
return 0;//Fib(0)
}
else if(n == 1)
{
return 1;//Fib(1)
}
else
{
return Fib(n - 1) + Fib(n - 2);
}
}
main函数部分:
int main()
{
int n = 0;
scanf("%d", &n);
int ret = Fib(n);
printf("%d", ret);
return 0;
}
整体实现效果:
==================================================================================================================================================
总结:拿到一个题目,若想判断其是否能使用递归,将它进行拆分计算,看看是否符合条件。
如若符合条件,此条件可以作为解题的关键,从而去使用,达到解题的目的。