递归(Recursion)快速上手指南【JS例子】

目录

递归是什么?

递归是一种 函数自己调用自己 的编程方式,用来解决 复杂但结构重复 的问题。

什么时候使用递归?

当问题能被拆成 与原问题结构相同但更小的子问题 时,就可以使用递归。

场景 示例
处理树形结构 菜单树、组织树、文件夹结构
链式结构 链表、路径寻找
重复计算 斐波那契、阶乘
深度遍历 DFS、查找嵌套结构
分治算法 快排、归并

递归的核心要素

要素 说明
🔹 终止条件 必须有,避免无限循环
🔹 递归调用 函数自己调用自己,处理子问题
🔹 返回结果 每层递归如何返回和组合结果

模版写法

javascript 复制代码
function recursion(data) {
  // 1. 终止条件(必须有!)
  if (满足结束条件) return 结果;

  // 2. 递归调用
  return recursion(缩小后的数据);
}

从简单到复杂的递归案例

求阶乘

javascript 复制代码
function factorial(n) {
  if (n === 1) return 1;  // 终止条件
  return n * factorial(n - 1);  // 递归调用
}

console.log(factorial(5)); // 120

斐波那契数列(有重复计算)

javascript 复制代码
function fib(n) {
  if (n <= 1) return n; // 终止条件
  return fib(n-1) + fib(n-2); // 递归调用
}
console.log(fib(6)); // 8

斐波那契数列是什么?

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...

从第三个数开始,每个数 = 前两个数相加。也就是:第0项:0,第1项:1,第2项 = 0 + 1 = 1,第3项 = 1 + 1 = 2,第4项 = 1 + 2 = 3,第5项 = 2 + 3 = 5,第6项 = 3 + 5 = 8

斐波那契数列的数学公式

javascript 复制代码
F(0) = 0
F(1) = 1
F(n) = F(n-1) + F(n-2)

数组求和

javascript 复制代码
function sumArray(arr) {
  if (arr.length === 0) return 0;
  return arr[0] + sumArray(arr.slice(1));
}
console.log(sumArray([1,2,3,4])); // 10

扁平化多维数组

javascript 复制代码
function flatten(arr) {
  let res = [];
  for (const item of arr) {
    if (Array.isArray(item)) {
      res = res.concat(flatten(item)); // 递归展开
    } else {
      res.push(item);
    }
  }
  return res;
}

console.log(flatten([1, [2, [3, [4]], 5]]));  

查找树形结构节点

javascript 复制代码
function findNode(tree, id) {
  for (const node of tree) {
    if (node.id === id) return node; // 终止条件
    if (node.children) {
      const found = findNode(node.children, id); // 递归调用
      if (found) return found;
    }
  }
  return null;
}

树结构映射(渲染前端菜单/组件树)

javascript 复制代码
function mapTree(nodes) {
  if (!nodes || nodes.length === 0) return [];
  return nodes.map(node => ({
    label: node.name,
    value: node.id,
    children: mapTree(node.children) // 递归处理子节点
  }));
}

深度遍历 DOM 节点

javascript 复制代码
function traverseDOM(node) {
  console.log(node.tagName);
  node.childNodes.forEach(child => traverseDOM(child));
}
traverseDOM(document.body);

查找嵌套评论(评论树展开)

javascript 复制代码
function collectComments(comments) {
  let result = [];
  comments.forEach(c => {
    result.push(c.text);
    if (c.replies) {
      result = result.concat(collectComments(c.replies));
    }
  });
  return result;
}

快速排序(分治递归)

javascript 复制代码
function quickSort(arr) {
  if (arr.length <= 1) return arr; // 终止条件
  const pivot = arr[0];
  const left = arr.slice(1).filter(x => x <= pivot);
  const right = arr.slice(1).filter(x => x > pivot);
  return [...quickSort(left), pivot, ...quickSort(right)];
}

计算对象嵌套属性数量

javascript 复制代码
function countKeys(obj) {
  let count = 0;
  for (const key in obj) {
    count++;
    if (typeof obj[key] === 'object' && obj[key] !== null) {
      count += countKeys(obj[key]); // 递归
    }
  }
  return count;
}

递归vs循环

场景 适合递归 适合循环
树结构
链表
数组遍历
深度搜索 DFS
性能敏感
可读性要求

树 = 递归优先;线性 = 循环优先

相关推荐
宠..1 小时前
安装 Qt VS Tool 插件
开发语言·qt
我叫张小白。1 小时前
Vue3 基本生命周期:组件的一生之旅
前端·javascript·vue.js·前端框架·vue3
QH_ShareHub1 小时前
R 包中的生命周期触发函数全解析
前端·javascript·数据库
未来之窗软件服务1 小时前
幽冥大陆(三十九)php二维数组去重——东方仙盟筑基期
android·开发语言·算法·php·仙盟创梦ide·东方仙盟·东方仙盟sdk
AI3D_WebEngineer1 小时前
企业级业务平台项目设计、架构、业务全解之平台篇
前端·javascript·vue
程序猫.1 小时前
Java零基础入门:集合进阶(下)
java·开发语言
菜鸟-012 小时前
QT:BMS_TTL
开发语言·qt
sali-tec2 小时前
C# 基于halcon的视觉工作流-章65 点云匹配-基于形状
开发语言·人工智能·算法·计算机视觉·c#
不会c嘎嘎2 小时前
【C++】深入理解多态:从用法到原理
开发语言·c++