目录
【前言】
在C语言中,函数递归被广泛应用于各个领域,无论是数据结构的实现还是算法的设计,都可以借助递归来简化问题。
1.函数递归的介绍
函数递归是指一个函数在其自身的定义中调用自身的过程。通过这种方式,函数可以重复执行相同的操作,从而解决更复杂的问题。递归函数通常包含两部分:基本情况和递归调用
写⼀个最简单的C语言递归代码:
int main()
{
printf("666\n");
main();//main函数中⼜调⽤了main函数
return 0;
}
该结果会无限打印666,代码最终也会陷入死递归,导致栈溢出。
2.递归的限制条件
-
达到基本情况:递归函数应该定义一个或多个基本情况,当满足这些条件时,递归将停止。基本情况应该是问题规模最小或无法再分解的情况,确保递归能够在有限次数内结束。
-
收敛性:递归调用的参数或输入应该朝着基本情况收敛。换句话说,每次递归调用都应该使问题规模减小,直到达到基本情况。如果参数或输入没有逐渐收敛,递归可能会陷入无限循环。
3.举例
举例一:求n的阶乘
代码实现
int Fac(int n)
{
if (n == 0)
return 1;
else
return n * Fac(n - 1);
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = Fac(n);
printf("%d的阶乘是%d\n", n, ret);
}
结果
当 n==0 的时候,n的阶乘是1,其余n的阶乘都是可以通过公式计算。假设Fac(n)就是求n的阶乘,那么Fac(n-1)就是求n-1的阶乘。
举例二:输⼊⼀个整数m,打印这个按照顺序打印整数的每⼀位。
代码实现
int Print(int n)
{
if (n > 9)
{
Print(n / 10);
}
printf("%d ", n % 10);
}
int main()
{
int n = 0;
scanf("%d", &n);
Print(n);
return 0;
}
结果
这个题目我们应该想到如何得到每一位数字,当1234%10,我们可以得到4;1234/10,我们可以得到123。以此类推。
4.递归与迭代
递归通常使用较少的代码来实现,但可能会占用大量的系统资源和堆栈空间。
迭代是一种循环结构,通过多次重复执行相同的操作来解决问题。在迭代中,问题被划分为可重复的步骤,每个步骤都需要执行相同的操作。迭代通常需要编写更多的代码来实现,但使用的堆栈空间较少,因此对系统资源的消耗也较小。
举例一我们可以用以下方法来实现
int Fac(int n)
{
int i = 0;
int m = 1;
for (i = 1; i <= n; i++)
{
m *= i;
}
return m;
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = Fac(n);
printf("%d的阶乘是%d\n", n, ret);
}
此方法相对递归来说效率更高
例如:求第n个斐波那契数
第一个版本
int Fib(int n)
{
if (n <= 2)
return 1;
else
return Fib(n - 1) + Fib(n - 2);
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = Fib(n);
printf("第%d个斐波那契数是%d\n", n, ret);
}
该代码简单易写,但是会造成大量的重复计算,效率是很低的。
第二个版本
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;
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = Fib(n);
printf("第%d个斐波那契数是%d\n", n, ret);
}
这个代码明显效率会提高很多。
5.青蛙跳台阶问题
int JumpWays(int n)
{
if (n > 0)
{
if (n == 1)
return 1;
else if (n == 2)
return 2;
else
return JumpWays(n - 1) + JumpWays(n - 2);
}
else
return 0;
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = JumpWays(n);
printf("青蛙跳上 %d 级台阶共有 %d 种方法\n", n, ret);
}