在C语言的基础学习中我们已经学会了循环语句的使用,回顾一下已经学习了for/while/do while循环语句
知识前提:栈帧,循环,if语句,函数的运用
什么是函数递归?
函数在函数体内调用自身的方法就叫做函数递归,下面是简单的函数调用自身,称为直接递归
void home()
{
home();
}
循环顾名思义就是重复执行代码,而函数递归则是函数在条件前提下调用自身,其运行程度往往比循环更加复杂。但函数递归的代码相比循环语句而言更加简洁,循环语句的表达往往更加繁琐。
接下来我将用一个简单的例子-斐波那契数的计算运用函数递归
先回顾一下斐波那契数的定义:从第二项开始,后面的每一项等于前两项之和
先写出主函数main(),定义一个整数型变量n初始值为0,使用scanf函数读取一个整数,存入n的地址。
int main()
{
int n = 0;
scanf("%d",&n);
return 0;
}
接着我们在主函数之前对斐波那契函数进行定义,给函数起名为fib,类型为int,需要知道斐波那契数的前两项是特殊的,即0和1,需要判别scanf函数输入的是否为第0项或第1项,以及给出相应的返回值,并给出正常项的返回值。其中前两项我们可以利用if语句轻松实现
定义int类型的n(主函数已初始为0)
int fib(int n)
{
if(n == 0)
return 0;
else if(n == 1)
return 1;
}
前两项讨论完,接下来再写正常项的返回值,及第3~正无穷项,此时涉及函数递归思想,可以理解为套娃
int fib(int n)
{
if(n == 0)
return 0;
else if(n == 1)
return 1;
else
return fib(n - 1) + fib(n - 2);
}
如果scanf给出4,则直接先来到else的返回值,程序开始计算fib(3) + fib(2),就发生类似套娃效应,fib(3)又来到else的返回值,程序开始计算fib(2) + fib(1),而这两次得到的fib(2)又要返回到else的返回值,计算fib(1) + fib(0),直至可直接回归返回值(只有fib(1)和fib(0))
暂时没找到好用的画图工具,一旦找到会给出清晰的图解,也可借助ai生成帮助理解
此时我们再来返回到主函数区块,完善主函数,定义一个变量r,赋予函数fib(n)的返回值,再将其打印出来,最终得到我们完整的主函数
int main()
{
int n = 0;
scanf("%d",&n);
int r = fib(n);
printf("%d\n",r);
return 0;
}
头文件应该不用再强调,毕竟初学,这里还是强调一下
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
此时我们对于斐波那契数的计算已经实现,运行输入项数即可
但是我们会发现随着项数的增加,程序的计算时间也会增加,甚至发生卡顿现象,这是因为虽然代码看起来十分简洁,但是程序背后会经历十分庞大的运算,可搜斐波那契数金字塔相关图献加以了解其数字运算的庞大
例如n=50,运算时长可能长达30秒,若数字庞大也存在超出int范围的风险,此时需改用long long
简洁来说,在计算庞大的前提下,递归程序会影响性能
因为程序的每一次函数调用,都需要为本次函数调用在内存的栈区,申请一块内存空间来保护函数调用期间的各种局部变量的值,这块空间叫作运行时堆栈,即函数栈帧
函数不返回,函数对应的栈帧空间会一直占用,所以如果函数调用中存在递归调用的话,每一次递归函数调用都会开启属于自己的栈帧空间,直到函数递归不再继续,开始回归,然后才逐层释放栈帧空间
采用函数递归的方式完成代码,递归层次太深,会浪费很多栈帧空间,可能会引起栈溢出的情况,即可能发生崩溃
优化栈溢出的方式可以采用尾溢出,但是部分编译器不支持,也没过多了解,这里不再给出实例
由以上斐波那契数的实例,结合之前学过的循环语句,我们可以总结出以下
当一个问题非常复杂,难以用循环的方式实现,此时可以考虑递归的简洁性,递归的深度在一定范围内不会造成大量堆积,可以大胆使用递归写法
也可用ai辅助理解与优化代码
ps:内容可能存在不严谨的部分,以上仅为个人观点,最后修改时间2026 8 26 23:58
内容仅为个人学习C语言过程中的记录,不具有权威性,不足的地方欢迎指出

4058

被折叠的 条评论
为什么被折叠?



