递归就是函数调用自己!就像俄罗斯套娃一样,函数里面又调用自己。
// 计算阶乘的例子
function factorial(n) {
if (n === 1) {
return 1; // 基础情况:最小的套娃
}
return n * factorial(n - 1); // 递归调用:打开下一个套娃
}
想象你在桌子上叠盘子,每调用一次函数就放一个盘子。如果叠得太高,桌子就撑不住了!
// 普通递归 - 会占用大量栈空间
function factorial(n) {
if (n === 1) return 1;
return n * factorial(n - 1); // 这里需要等待递归结果
}
// 调用 factorial(5) 时:
// factorial(5) 等待 factorial(4)
// factorial(4) 等待 factorial(3)
// factorial(3) 等待 factorial(2)
// factorial(2) 等待 factorial(1)
// factorial(1) 返回 1
// 然后一层层返回...
// 尾递归版本 - 栈空间使用很少
function factorialTail(n, accumulator = 1) {
if (n === 1) {
return accumulator; // 直接返回结果
}
return factorialTail(n - 1, n * accumulator); // 尾递归调用
}
// 调用 factorialTail(5) 时:
// factorialTail(5, 1) → factorialTail(4, 5)
// factorialTail(4, 5) → factorialTail(3, 20)
// factorialTail(3, 20) → factorialTail(2, 60)
// factorialTail(2, 60) → factorialTail(1, 120)
// factorialTail(1, 120) → 返回 120
| 特性 | 普通递归 | 尾递归 |
|---|---|---|
| 栈空间使用 | ❌ 大量栈空间 | ✅ 少量栈空间 |
| 性能 | ❌ 可能栈溢出 | ✅ 可优化为循环 |
| 递归位置 | ❌ 递归后还有操作 | ✅ 递归是最后操作 |
| 理解难度 | 😊 相对简单 | 🤔 需要思考 |