上一篇文章我们详细介绍了C语言中函数的基础内容。在这一节中,我们讲来继续深入学习一种函数中好用的技巧——递归。
目录
一、递归的定义
二、栈溢出原理
2.1 内存分区示意图:
三、递归的必要条件
3.1 示例:打印数字每一位
四、递归的经典应用
4.1 求字符串长度(模拟strlen)
4.2. 汉诺塔问题
4.3. 青蛙跳台阶(斐波那契数列变种)
五、递归与迭代的对比
5. 1 示例:斐波那契数列
递归是函数通过调用自身来解决问题的一种编程技巧。它的核心思想是“大事化小”,即将一个复杂的问题分解为多个与原问题相似但规模更小的子问题,直到问题简化到可以直接解决。
例如,计算阶乘 n!
的递归实现:
int factorial(int n) {
if (n == 0) return 1; // 终止条件
return n * factorial(n - 1); // 递推关系
}
这里,n!
被分解为 n * (n-1)!
,直到 n=0
时终止递归。
递归调用依赖内存中的栈区存储函数调用信息。每次递归调用都会在栈中分配一块空间(称为栈帧),用于保存局部变量和返回地址。若递归深度过大,栈空间会被耗尽,导致栈溢出(Stack Overflow)。
提示:递归深度需谨慎控制,避免无限递归。例如,缺少终止条件的斐波那契递归会迅速导致栈溢出。
递归必须满足两个核心条件:
void printDigits(int n) {
if (n > 9) { // 终止条件:n为个位数时不再递归
printDigits(n / 10); // 递推:去掉最后一位
}
printf("%d ", n % 10); // 打印当前最后一位
}
输入 1234
,输出 1 2 3 4
。每次递归调用 n
的规模缩小,直到 n <= 9
。
思路:从最简单的问题解决,哪个容易就解决哪个,然后拆成多个相似的规模小的问题,思路类似于倒推法+拆解,不理解就画图可视化,递归完后从哪里来,回哪里去
strlen
)int myStrlen(const char* str) {
if (*str == '\0') return 0; // 终止条件:空字符
return 1 + myStrlen(str + 1); // 递推:指针后移一位
}
关键点:递归到字符串末尾的空字符 \0
时终止。
void hanoi(int n, char A, char B, char C) {
if (n == 1) {
printf("Move disk 1 from %c to %c\n", A, C);
return;
}
hanoi(n - 1, A, C, B); // 将n-1个盘子从A移到B(借助C)
printf("Move disk %d from %c to %c\n", n, A, C);
hanoi(n - 1, B, A, C); // 将n-1个盘子从B移到C(借助A)
}
思路:将问题分解为移动 n-1
个盘子和移动最底层的盘子,底层是分步乘法原理。
青蛙一次可以跳1或2阶台阶,问跳上 n
阶有多少种方法:
int jump(int n) {
if (n <= 2) return n; // 终止条件:1阶1种,2阶2种
return jump(n - 1) + jump(n - 2); // 递推:最后一步跳1或2阶
}
思路:分类讨论最后一步为一步和两步的情况,底层是分类加法原理。
递归 | 迭代 |
---|---|
代码简洁,符合直觉 | 代码稍复杂,需手动管理循环变量 |
可能栈溢出,效率低(如斐波那契) | 无栈溢出风险,效率高 |
适合分治问题(如汉诺塔) | 适合线性计算(如阶乘、累加) |
// 递归(效率低)
int fib(int n) {
if (n <= 2) return 1;
return fib(n-1) + fib(n-2);
}
// 迭代(效率高)
int fibIter(int n) {
int a = 1, b = 1, c;
for (int i = 3; i <= n; i++) {
c = a + b;
a = b;
b = c;
}
return b;
}
总结:如果功能实现用递归求解简单,容易理解,并且写完后无明显缺陷,用递归解决,而如果用递归写有缺陷(如栈溢出,效率低),则用非递归的迭代实现
递归是C语言中一种强大的工具,其核心在于将复杂问题拆解为相似子问题。本文我们通过对递归的经典案例(如汉诺塔、阶乘)的练习,可以深入理解递归的思维模式。然而,递归并非万能,需结合实际场景权衡其与迭代的优劣。在下篇文章中,我们将进行C语言中数组的学习,敬请期待!
作者其他文章链接:
初识C语言—人生若只如初见(持续更新中!)-CSDN博客
[C语言初阶]分支和循环语句练习-CSDN博客
[C语言初阶]猜数字小游戏实现-CSDN博客
Gitee详细使用教程_gitee 教程-CSDN博客
[C语言初阶]函数-CSDN博客