1. 递归的本质与基本概念
递归(Recursion)是C语言中一种强大的编程技术,它允许函数直接或间接地调用自身。这种自我调用的特性使得递归特别适合解决那些可以分解为相同问题的子问题的情况。
1.1 递归的核心特征
递归函数具有三个关键特征:
- 自我调用:函数在其定义中调用自身
- 基本情况:必须包含一个或多个终止条件(base case)
- 递归情况:每次调用都向基本情况推进
c复制void recursiveFunction(int n) {
if(n <= 0) { // 基本情况
return;
}
printf("%d\n", n);
recursiveFunction(n-1); // 递归调用
}
1.2 递归与迭代的对比
递归和迭代(循环)都可以解决重复性问题,但各有优劣:
| 特性 | 递归 | 迭代 |
|---|---|---|
| 代码简洁性 | 高 | 中 |
| 内存消耗 | 高(栈空间) | 低 |
| 执行效率 | 较低(函数调用开销) | 高 |
| 适用场景 | 树/图遍历、分治算法 | 简单循环、线性处理 |
提示:递归虽然代码简洁,但在性能敏感的场景下应谨慎使用,特别是当递归深度可能很大时。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 递归的工作原理与栈机制
2.1 调用栈的运作方式
每次递归调用都会在内存的调用栈中创建一个新的栈帧(stack frame),包含:
- 函数参数
- 局部变量
- 返回地址
c复制int factorial(int n) {
if(n <= 1) return 1;
return n * factorial(n-1);
}
当计算factorial(3)时,栈的变化如下:
- factorial(3)调用
- 栈:[factorial(3)]
- factorial(3)调用factorial(2)
- 栈:[factorial(3), factorial(2)]
- factorial(2)调用factorial(1)
- 栈:[factorial(3), factorial(2), factorial(1)]
- factorial(1)返回1
- 栈:[factorial(3), factorial(2)]
- factorial(2)返回2*1=2
- 栈:[factorial(3)]
- factorial(3)返回3*2=6
- 栈:[]
2.2 递归深度与栈溢出
系统为每个程序分配的栈空间有限(通常几MB),递归深度过大会导致栈溢出:
c复制void infiniteRecursion() {
infiniteRecursion(); // 无限递归,最终导致栈溢出
}
注意:在Linux系统中,默认栈大小约为8MB,Windows约为1MB。可通过ulimit -s(Linux)或编译器选项调整栈大小。
3. 递归的经典应用场景
3.1 数学问题求解
阶乘计算
c复制unsigned long long factorial(unsigned int n) {
if(n <= 1) return 1;
return n * factorial(n-1);
}
斐波那契数列
c复制int fibonacci(int n) {
if(n <= 0) return 0;
if(n == 1) return 1;
return fibonacci(n-1) + fibonacci(n-2);
}
警告:朴素递归实现的斐波那契数列时间复杂度为O(2^n),实际应用中应使用记忆化或迭代方法。
3.2 数据结构遍历
二叉树遍历
c复制struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
};
void inorderTraversal(struct TreeNode* root) {
if(root == NULL) return;
inorderTraversal(root->left);
printf("%d ", root->val);
inorderTraversal(root->right);
}
链表反转
c复制struct ListNode {
int val;
struct ListNode *next;
};
struct ListNode* reverseList(struct ListNode* head) {
if(head == NULL || head->next == NULL)
return head;
struct ListNode* newHead = reverseList(head->next);
head->next->next = head;
head->next = NULL;
return newHead;
}
3.3 分治算法
快速排序
c复制void quickSort(int arr[], int low, int high) {
if(low < high) {
int pi = partition(arr, low, high);
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
