前言
函数的递归是函数的重要部分,全面我们写了一篇关于C语言的自定义函数,相信大家对函数也有了一定的了解,那么这里单独把函数递归拿出来讲是为了讲的更清楚一点,但是如果有讲错的地方也请大佬指正,有不够详细的地方也请大家多多海涵
一、函数递归的介绍
1. 什么是函数的递归?
递的递推的意识,归是归来的意思,所以可以理解为一个函数进行了递推与回归,递归也就是一个函数调用它自己的过程,函数体中调用自己是递推,当最后一个被调用的函数结束后往回就是归来,我知道这样讲是有点抽象的,但是后面让我们慢慢理解
2. 递归的好处
- 代码简化减少重复代码: 递归是函数调用自身来解决问题,代码会相对简洁
- 问题分解: 递归允许你将复杂问题分解成更小、更易于管理的子问题。这种分解有助于以模块化的方式解决问题。
至于以上的好处我们会在后面的代码中体现
二、函数递归的实现
1. 最简单的函数递归
#include <stdio.h>
int main() {
main();
return 0;
}
上面我们在main函数中调用了main函数来实现最简单的递归,但是这个递归是没有停止条件的,所以,它会导致严重我问题:栈溢出
Stack overflow
栈溢出
2. 函数递归的限制条件
为了避免我们递归出现上面的情况,我们需要给实现递归安置一些限制条件
- 递归存在限制条件,当满足这个限制条件的时候,递归便不再继续
- 每次递归调用之后越来越接近这个限制条件
我们举个例子说明一下这两个条件
//使用递归求n的阶乘
#include <stdio.h>
int NFactorial(int n) {
if (n > 1)
return n * NFactorial(n - 1);
return 1;
}
int main() {
int n = 0;
printf("请输入n的值:");
scanf("%d", &n);
printf("%d 的阶乘为:%d\n", n, NFactorial(n));
return 0;
}
上面我们使用递归函数进行了对1~n的阶乘求值,下面我们分析一下递归函数中的两个限制条件。
第一,函数的结束条件其实是当 n 的值为 1 时,函数递归就会结束
第二,函数在调用自身时传入的值是 n-1 ,每次递归调用之后越来越接近 n 的值等于 1 这个限制条件
3. 函数递归的过程图解
为了方便了解,我们可以画出递归展开图,更直观的展示递归的过程
通过这个图,我们可以更加直观的理解函数递归的过程
三、函数递归与内存空间
在C语言中每一次函数调用,都需要为本次函数调用在内存的栈区,申请一块内存空间来保存函数调用期间的各种局部变量的值,这块空间被称为运行时堆栈,或者函数栈帧。
关于函数栈帧的创建与销毁在我的C语言栏目文章中我专门的讲解哦,大家可以去看看!
函数递归在内存中的细节: 函数不返回,函数对应的栈帧空间就一直占用,所以如果函数调用中存在递归调用的话,每一次递归函数调用都会开辟属于自己的栈帧空间,直到函数递归不再继续,开始回归,才逐层释放栈帧空间。也就是说函数递归这个过程中函数的栈帧不断创建一直往栈上累加,直到函数达到限制条件,函数的栈帧才会从上往下开始释放。
注: 如果递归的深度太深,栈帧过多的创建则会导致栈溢出
四、End
对于函数递归我们就讲到这里,函数的递归是一个非常巧妙的方法,可以帮助我们把复杂的问题化简为简单的小问题,如上面求n的阶乘,我们要知道5的阶乘,那我们知道4的阶乘后就可以用5乘于4的阶乘得到5的阶乘,而需要知道4的阶乘,我们可以在知道3的阶乘后,用4乘于3的阶乘得到,以此类推。 最后谢谢大家的阅读,希望对大家有帮助!