JS 二叉树入门:从概念到遍历,手把手教你吃透

0 阅读9分钟

JS 二叉树入门:从概念到遍历,手把手教你吃透

作为 JS 初学者,提到二叉树可能会觉得头大,总觉得这是算法里的 “硬骨头”。但其实二叉树的核心逻辑特别简单,尤其是用 JS 来实现,只需要掌握对象和函数的基础就能上手。这篇文章会从二叉树的基本概念讲起,一步步带你实现二叉树的前序、中序、后序、层序四种遍历,全程代码落地,新手也能轻松看懂~

一、先搞懂:什么是树?什么是二叉树?

在学二叉树之前,我们先从最基础的开始理解,它其实是对自然界树的抽象,和我们平时学的数组、对象这种线性结构不一样,树是非线性数据结构,核心是 “一个根,多分支”。

1. 树的核心概念(大白话版)

不用记学术定义,记住这几个关键词就行:

  • 根节点:树的 “树根”,整棵树只有一个根节点,是所有节点的起点;
  • 子节点 / 父节点:分支上的节点,上层是父节点,下层是子节点;
  • 叶子节点:树的 “树叶”,也就是没有子节点的节点(度为 0 的节点);
  • :一个节点有几个子分支,就是几度(比如有 2 个子节点,度为 2);
  • 层次:根节点是第 1 层,根的子节点是第 2 层,依次往下数。

我用一张图来看一下一个二叉树模型

屏幕截图 2026-02-15 151745.png

2. 二叉树:树的 “限定版”

二叉树是树中最常用的类型,它的规则特别简单,总结就一句话:要么空,要么有根 + 左子树 + 右子树,且左右子树也必须是二叉树。这里有两个关键注意点,新手很容易踩坑:

  1. 二叉树不是 “度为 2 的树”,节点的度可以是 0、1、2(比如叶子节点度为 0,只有左子节点的节点度为 1);
  2. 左右子树有严格顺序,不能随便交换,左就是左,右就是右。

3. 二叉树的节点结构

在 JS 里,二叉树的每个节点就是一个对象,核心包含三个部分:

  • 数据域 val:节点存储的数值 / 内容;
  • 左节点引用 left:指向左子节点,没有就为 null
  • 右节点引用 right:指向右子节点,没有就为 null

这就是二叉树的最小单元,整棵二叉树就是由无数个这样的节点嵌套组合而成的。

二、JS 实现二叉树:两种创建方式

理解了节点结构,我们就能手动创建一棵二叉树了,JS 里有两种常用方式,对象字面量构造函数,新手推荐先学对象字面量,更直观;构造函数适合后续动态创建节点。

方式 1:对象字面量(直观易上手)

直接用嵌套对象表示,从根节点开始,一层层往下写,没有子节点就写 null,一眼就能看清树的结构:

// 一棵简单的二叉树:根A,左子树B(子D、E),右子树C(子F)
const root = {
    val: 'A',
    left: {
        val: 'B',
        left: { val: 'D', left: null, right: null },
        right: { val: 'E', left: null, right: null }
    },
    right: {
        val: 'C',
        left: null,
        right: { val: 'F', left: null, right: null }
    }
}

方式 2:构造函数(动态创建)

先写一个节点的构造函数,再通过实例化节点、设置左右引用,组装成树,适合需要动态添加 / 删除节点的场景:

// 二叉树节点构造函数
function TreeNode(val) {
    this.val = val; // 数据域
    this.left = null; // 左子节点默认null
    this.right = null; // 右子节点默认null
}

// 实例化节点
const root = new TreeNode(1); // 根节点1
const node2 = new TreeNode(2); // 左子节点2
const node3 = new TreeNode(3); // 右子节点3
// 组装树:设置根节点的左右子节点
root.left = node2;
root.right = node3;
// 给node2添加左右子节点
node2.left = new TreeNode(4);
node2.right = new TreeNode(5);

可视化树结构

这里放一张二叉树模型图,对应上面的代码,能更直观地看到节点的层级和左右关系:

屏幕截图 2026-02-15 162710.png

三、二叉树的核心:遍历!(递归版)

遍历就是按一定顺序访问二叉树的所有节点,且每个节点只访问一次。二叉树的遍历是面试和开发中的核心考点,其中前序、中序、后序是最基础的三种,这三种都可以用递归实现,而递归的逻辑和二叉树的定义高度契合,新手只要掌握规律,三分钟就能写出来。

1. 先搞懂:递归遍历的核心规律

二叉树的递归遍历,左右子树的访问顺序永远是左→右,唯一的区别是根节点的访问时机,这也是前 / 中 / 后序的命名由来:

  • 前序:根节点 → 左子树 → 右子树(根在最前)
  • 中序:左子树 → 根节点 → 右子树(根在中间)
  • 后序:左子树 → 右子树 → 根节点(根在最后)

递归的两个核心要点,缺一不可:

  1. 递归退出条件:当节点为 null 时,直接返回(没有子节点,无需遍历);
  2. 重复执行逻辑:按照对应顺序,访问根节点、递归左子树、递归右子树。

2. 前序遍历(根→左→右)

实现代码
// 前序遍历:递归版
function preorder(root) {
    // 退出条件:节点为null,直接返回
    if (!root) return;
    // 1. 先访问根节点
    console.log(root.val);
    // 2. 递归遍历左子树
    preorder(root.left);
    // 3. 递归遍历右子树
    preorder(root.right);
}

// 调用:传入根节点,即可按顺序打印节点
preorder(root); // 输出:A B D E C F(对应上面的对象字面量树)
遍历过程可视化

这里放一张前序遍历过程图,一步步展示根节点的访问和左右子树的递归顺序,后面的中序、后序遍历都于此差不多:

屏幕截图 2026-02-15 162740.png

屏幕截图 2026-02-15 163846.png

屏幕截图 2026-02-15 163905.png

屏幕截图 2026-02-15 164056.png

屏幕截图 2026-02-15 164119.png 我就先到遍历到B,后面的遍历过程都和这差不多,大家可以以此类推

3. 中序遍历(左→根→右)

只需要把根节点的访问语句移到左右子树递归之间,其他代码完全不变,新手可以直接复制改位置~

实现代码
// 中序遍历:递归版
function inorder(root) {
    if (!root) return;
    // 1. 先递归遍历左子树
    inorder(root.left);
    // 2. 再访问根节点
    console.log(root.val);
    // 3. 最后递归遍历右子树
    inorder(root.right);
}

inorder(root); // 输出:D B E A C F

4. 后序遍历(左→右→根)

同理,把根节点的访问语句移到左右子树递归之后即可。

实现代码
// 后序遍历:递归版
function postorder(root) {
    if (!root) return;
    // 1. 递归遍历左子树
    postorder(root.left);
    // 2. 递归遍历右子树
    postorder(root.right);
    // 3. 最后访问根节点
    console.log(root.val);
}

postorder(root); // 输出:D E B F C A

小总结

递归版的前 / 中 / 后序遍历,代码几乎一模一样,唯一的区别就是console.log(root.val)的位置,记住这个规律,再也不用死记硬背了!

四、层序遍历:按 “层” 走,迭代版(队列实现)

除了前 / 中 / 后序的深度优先遍历,还有一种常用的广度优先遍历—— 层序遍历,也就是从上到下、从左到右,按层级访问所有节点(比如根节点第 1 层,子节点第 2 层,依次往下)。

层序遍历不用递归,而是用队列来实现,核心思路是先进先出:把每一层的节点入队,访问完后再把其子节点入队,直到队列为空。

实现代码

// 层序遍历:迭代版(队列实现)
function levelOrder(root) {
    // 空树直接返回空数组
    if (!root) return [];
    const result = []; // 存储遍历结果
    const queue = [root]; // 初始化队列,入队根节点

    // 队列不为空时,持续遍历
    while (queue.length) {
        const node = queue.shift(); // 队头出队(访问当前节点)
        result.push(node.val); // 把节点值存入结果
        // 左子节点存在,入队
        if (node.left) queue.push(node.left);
        // 右子节点存在,入队
        if (node.right) queue.push(node.right);
    }
    return result; // 返回遍历结果
}

// 调用
console.log(levelOrder(root)); // 输出:['A','B','C','D','E','F']

层序遍历核心逻辑

  1. 初始化队列,将根节点入队,这是第 1 层;
  2. 出队队头节点,访问它并存入结果;
  3. 把该节点的左、右子节点依次入队(这是下一层的节点);
  4. 重复步骤 2-3,直到队列为空,所有层级都访问完毕。

五、新手必看:常见问题 & 小技巧

  1. 递归看不懂? :把递归看成 “重复执行相同的小事”,不用纠结递归的深层调用过程,只要写对退出条件单次执行逻辑就行,计算机会自己处理嵌套;
  2. 树的结构看不清? :写代码时可以把树的结构按层级缩进,或者画一张简易的树图,对应代码来看;
  3. 遍历结果验证? :先手动按顺序数一遍节点,再运行代码对比,快速排查问题;
  4. 为什么层序用队列? :因为层序需要 “先进先出”,而队列的特性正好匹配;如果用栈,就会变成深度优先遍历了。

六、最后总结

二叉树其实是 JS 初学者入门算法的绝佳选择,核心内容就这几点,吃透了就能举一反三:

  1. 二叉树的节点是嵌套对象,核心包含valleftright
  2. 前 / 中 / 后序遍历(递归):左右顺序固定,根节点时机不同
  3. 层序遍历(迭代):借助队列,按层级从上到下、从左到右访问;
  4. 递归的关键:退出条件 + 重复逻辑,不要纠结深层调用过程。

这篇文章的代码都是最基础的实现,新手可以直接复制到浏览器控制台 / VS Code 里运行,结合图片理解遍历过程。后续可以在此基础上拓展,比如遍历结果存入数组(而非打印)、二叉树的增删改查二叉搜索树等内容,一步一个脚印,算法其实一点都不难~

最后:如果觉得这篇文章有用,欢迎点赞收藏~ 后续会继续更新 JS 算法的入门内容,从基础到进阶,和大家一起打怪升级~