Z
ZHANK

递归函数

递归思想、阶乘/斐波那契/汉诺塔、栈溢出风险

递归函数

函数调用自身——递归让复杂问题(树遍历、分治算法)变得简洁优雅。但 C 的递归要格外小心栈溢出。

学完本章你将: 掌握递归思想、阶乘/斐波那契/汉诺塔、递归 vs 迭代。


递归的本质

c
#include <stdio.h>

// 阶乘:n! = n * (n-1)!
int factorial(int n) {
    if (n <= 1) return 1;            // 基准条件
    return n * factorial(n - 1);     // 递归调用
}

int main() {
    printf("5! = %d\n", factorial(5));  // 120
    return 0;
}

每次递归调用都会在栈上分配新的栈帧。必须有停止条件,否则无限递归耗尽栈空间。


斐波那契数列

c
int fib(int n) {
    if (n <= 1) return n;
    return fib(n - 1) + fib(n - 2);
}

// ⚠️ 这是 O(2^n) 的指数级复杂度!
// fib(50) 需要几十亿次调用,永远算不完。
// 实际开发用迭代或记忆化搜索。

迭代版(更好)

c
int fibIter(int n) {
    if (n <= 1) return n;
    int a = 0, b = 1;
    for (int i = 2; i <= n; i++) {
        int t = a + b;
        a = b;
        b = t;
    }
    return b;
}

汉诺塔

c
void hanoi(int n, char from, char to, char aux) {
    if (n == 1) {
        printf("%c → %c\n", from, to);
        return;
    }
    hanoi(n - 1, from, aux, to);
    printf("%c → %c\n", from, to);
    hanoi(n - 1, aux, to, from);
}
// hanoi(3, 'A', 'C', 'B');

⚠️ 栈溢出风险: C 函数调用栈通常只有几 MB。递归深度超过 ~10 万就可能崩溃。深度递归考虑用堆上的手动栈替代。