什么是递归
递归是指函数在执行过程中调用自身的编程技术。递归可以让程序更简洁、更易读,同时也可以解决某些复杂问题。在递归函数中,每次函数调用都会创建一个新的函数栈帧,直到达到递归出口,然后依次弹出栈帧,返回结果。递归需要谨慎使用,因为如果递归的深度过大,可能会导致堆栈溢出,造成程序崩溃。
#include <stdio.h>
int main()
{
printf("hello\n");
main();//在main函数中又调用了main函数
return 0;
}
上述就是一个简单的递归程序,该程序只是演示了递归的基本操作形式,因为每一次函数调用都要向栈区申请内存空间,这个代码最终会导致栈溢出(Stack overflow)而造成死循环。
递归思想:大事化小!!! 把一个大型问题层层转化为一个与原问题相似,但规模较小的子问题来求解,这就是递归的思考方式。
递归的限制条件
- 递归存在限制条件,当满足限制条件后递归不再继续。
- 每次递归调用后越来越接近这个限制条件
递归举例
接下来我向大家举个递归的例子方便大家理解:
计算n的阶乘(不考虑溢出),n的阶乘就是1~n的数字累积相乘。
我们知道n的阶乘公式:n! = n*(n-1)!,所以我,可以将n!转化为n*(n-1)!,然后(n-1)!又可以转换为(n-1)*(n-2)!,以此类推直到n=1或者0时便不再拆解。n的阶乘公式如下:
那我们就可以写出函数Fact求n的阶乘,假设Fact(n)就是求n的阶乘,那么Fact(n-1)就是求n-1的阶乘,函数如下:
#include <stdio.h>
int Fact(int n)
{
if(n<=0)
return 1;
else
return n*Fact(n-1);
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret=Fact(n);
printf("%d",ret);
return 0;
}
通过这种递归方式我们就可以实现一个数的阶乘。接下来我给大家看一张图
大家看到这个图是不是很容易想到递归?这个就是著名的斐波那契数列的递归公式!具体实现代码如下:
#include <stdio.h>
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\n", ret);
return 0;
}
当我们n输入为50的时候,需要很长时间才能算出结果,这个计算所花费的时间,是我们很难接受的,这也说明递归的写法是非常低效的,那是为什么呢?大家看 这仅仅是n=5时候的计算量。递归程序会不断的展开,在展开的过程中,我们很容易就能发现,在递归的过程中会有重复计 算,而且递归层次越深,冗余计算就会越多,通过计算我们可以得到在计算第40个斐波那契数的时候,使用递归方式,第3个斐波那契数就被重复计算了 39088169次,这些计算是非常冗余的。所以斐波那契数的计算,使用递归是非常不明智的,所以说有时候,递归虽好,但是也会引入⼀些问题,所以我们⼀定不要迷恋递归,适可而止就好。
在总结这篇关于C语言函数递归的文章之前,我们可以得出一个结论:递归是一个强大的编程技巧,可以帮助我们简化复杂的问题,提高代码的可读性和可维护性。在使用递归时,我们需要注意递归深度的问题,避免出现栈溢出等错误。同时,我们还需要理解递归的本质和原理,不断地进行练习和实践,才能真正掌握这一重要的编程技巧。最后,我希望读者们能够在学习和使用C语言函数递归的过程中,不断地提高自己的编程水平和技能,用好递归这一有力的武器,创造出更加优秀、高效的程序。