一.基础概念
1.1函数递归的定义
递归:递归其实是⼀种解决问题的⽅法,在C语⾔中,递归就是函数⾃⼰调⽤⾃⼰。
递归的思想: 把⼀个⼤型复杂问题层层转化为⼀个与原问题相似,但规模较⼩的⼦问题来求解;直到⼦问题不能再 被拆分,递归就结束了。所以递归的思考⽅式就是把⼤事化⼩(这种思考方式十分重要)的过程。 递归中的递就是递推的意思,归就是回归的意思。
1.2递归的限制条件
递归在书写的时候,有2个必要条件:
• 递归存在限制条件,当满⾜这个限制条件的时候,递归便不再继续。
• 每次递归调⽤之后越来越接近这个限制条件。
1.3递归的优缺点
优点:函数递归只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。
缺点:①如果函数递归使用不恰当,会导致栈溢出,因为每一次函数调用都会在栈区上申请内存空间。②每一次函数递归(函数调用)都会在函数栈帧上开辟一块空间,所谓的压栈。这样会大大降低我们代码的执行效率。
二.基础函数递归例题
2.1史上最简单的递归
#include <stdio.h>
int main()
{
printf("xixi\n");
main();//main函数中⼜调⽤了main函数
return 0;
}
上述就是⼀个简单的递归程序,只不过上⾯的递归只是为了演⽰递归的基本形式,不是为了解决问 题,代码最终也会陷⼊死递归,导致栈溢出(Stack overflow),就体现了缺点2.
2.2打印一个数的每一位
题目描述:
输入一个整数,按照顺序打印它的每一位,例如,输入:1234,输出1 2 3 4
解题思路:我们首先要思考如何把问题⼤事化⼩,把Print(1234) 打印1234每⼀位,拆解为⾸先Print(123)打印123的每⼀位,再打印得到的4 把Print(123) 打印123每⼀位,拆解为⾸先Print(12)打印12的每⼀位,再打印得到的3 直到Print打印的是⼀位数,直接打印就⾏。
如果输入的数字是小于10的,要如何得到它的每一位,我们可以想到是将它取余得到,这种输入输出数字的题,我们一定要想到取模和取余的方法,并且要有限制条件,每次函数递归后,都会越来越接近这个值。
设n为1234print(1234/10) + 1234%10 (=4)
print(123/10) + 123%10(=3)
print(12/10) + 12%10(=2)当n最后为1时,不满足我们给定的限制条件n>9时,即打印1%10得到1。
以此类推
Print(1234)
==>Print(123) + printf(4)
==>Print(12) + printf(3)
==>Print(1) + printf(2)
==>printf(1)
代码实现
#include<stdio.h>
int Print(int a)
{
if (a>9)
{
Print(a / 10);
}
printf("%d ", a % 10);
}
int main()
{
int n = 0;
scanf("%d", &n);
Print(n);
return 0;
}
画图推演
2.3BC171 牛牛的Hermite多项式
代码描述
#include <stdio.h>
int Fun(int a,int b)
{
if(a==0)
return 1;
else
if(a==1)
{
return 2*a;
}
else
return 2*b*Fun(a-1,b)-2*(a-1)*Fun(a-2,b);
}
int main() {
int n=0,x=0;
scanf("%d%d",&n,&x);
printf("%d",Fun(n,x));
return 0;
}
三.经典递归题
3.1求第n个斐波那契数递归和非递归的实现
计算斐波那契数递归实现求第n个斐波那契数
例如:
输入:5 输出:5
输入:10, 输出:55
输入:2, 输出:1
解题思路:斐波那系数是前两项加起来等于后一项:1,1,2,3,5,8,13…,所以我们可以以n<=2为限制条件,当n=1或2时,返回1,然后到n=3项时就是n=1项和n=2项之和,然后依次往后推,即Fib(n)就是Fib(n-1)和Fib(n-2)之和。
int Fib(int n)
{
if(n<=2)
return 1;
else
return Fib(n-1)+Fib(n-2);
}
画图推演
非递归实现
int Fib(int n)
{
int a = 1;
int b = 1;
int c = 1;
while(n>2)
{
c = a+b;
a = b;
b = c;
n--;
}
return c;
}
递归和非递归的方式,我们可以发现,递归在求比较大的斐波那契数时,递归程序会不断的展开,在展开的过程中,会有重复计算,⽽且递归层次越深,冗余计算就会越多。因此,我们不能什么都用递归来解决问题。
3.2BC166 小乐乐走台阶
描述
小乐乐上课需要走n阶台阶,因为他腿比较长,所以每次可以选择走一阶或者走两阶,那么他一共有多少种走法?
输入描述:
输入包含一个整数n (1 ≤ n ≤ 30)
输出描述:
输出一个整数,即小乐乐可以走的方法数。
解题思路:当只有一阶台阶时只有1种走法,二阶台阶时,有两种走法,因此我们可以得到当台阶数大于2时,有Fun(n-1)+Fun(n-2)种走法。此题是求第n个斐波那契数的演变。
代码解释:
#include <stdio.h>
int Fun(int n)
{
if(n<2)
return 1;
else
return Fun(n-1)+Fun(n-2);
}
int main() {
int a=0;
scanf("%d",&a);
printf("%d",Fun(a));
return 0;
}