你以为树只是画图?不——它是算法面试的“隐形主角”

如果数组是算法世界的地基

那么「树」,就是贯穿整个面试的 承重结构

无论你刷的是 力扣 Hot100 、校招面试,还是前端进阶,
树 & 二叉树一定会反复出现

  • DOM 是一棵树
  • Vue / React 的虚拟 DOM 是树
  • 文件系统是树
  • 递归,几乎是为树量身定做的

但很多人一提到树就懵:

"概念太多了..."

"遍历顺序老记混..."

"一写递归就心虚..."

这篇文章,我们用最接地气的方式,把树和二叉树一次讲透。


一、什么是「树」?------不是代码,是抽象能力

数据结构中的树,其实是对自然界树的抽象 🌲

我们先统一语言:

自然界 数据结构
树根 根节点 root
树枝 边 edge
分叉 子节点 child
叶子 叶子节点 leaf

一棵树的核心特征只有一个:

🌟 只有一个根节点,其余节点都从它延伸出来


二、树的几个"面试高频概念"(一定会被问)

1️⃣ 层次(level)

  • 根节点是 第 1 层
  • 子节点依次 +1

📌 面试常问:

"这棵树的第 k 层有多少节点?"


2️⃣ 高度(height)

⚠️ 容易混淆!

  • 从叶子节点开始算
  • 向上 +1

📌 面试爱问:

"树的高度是多少?"


3️⃣ 度(degree)

  • 一个节点有几个子树
  • 就是它的度

👉 叶子节点的度 = 0


三、什么是二叉树?别被"2"骗了 ❌

很多人第一反应是:

❌ "二叉树 = 每个节点最多 2 个孩子"

不完全对。

二叉树的真正定义👇

一棵二叉树:

  • 可以是 空树

  • 如果不是空树:

    • 必须由:
      根节点 + 左子树 + 右子树
    • 左右子树本身也是二叉树

📌 关键点只有一句话:

⚠️ 左右之分是"有顺序的",不能随便交换

所以:

  • ❌ 二叉树 ≠ 度为 2 的树
  • ✅ 二叉树 = 有左右语义的结构

四、二叉树节点的最小模型(JS)

kotlin 复制代码
function TreeNode(val){
  this.val = val
  this.left = this.right = null
}

只有 3 件事:

  • 数据域 val
  • 左孩子 left
  • 右孩子 right

📌 面试时你只要记住:
树 ≈ 节点 + 引用


五、为什么「树」和「递归」天生一对?

因为:树的定义本身就是递归的

  • 树 = 根 + 子树
  • 子树 = 更小的树
  • ......

📌 所以你刷到树题时,脑子里先问一句:

"这是不是一个可以拆成左右子树的重复问题?"

如果答案是 YES ------

👉 递归基本就稳了


六、二叉树遍历:面试最爱考的 4 种方式

一句话总纲

🔑 左右子树顺序永远不变,变的只有"根"什么时候输出


1️⃣ 前序遍历(Preorder)

👉 根 → 左 → 右

scss 复制代码
function preorder(root){
  if(!root) return
  console.log(root.val)
  preorder(root.left)
  preorder(root.right)
}

📌 适合:

  • 构建树
  • 拷贝树

2️⃣ 中序遍历(Inorder)

👉 左 → 根 → 右

scss 复制代码
function inorder(root){
  if(!root) return
  inorder(root.left)
  console.log(root.val)
  inorder(root.right)
}

📌 经典结论(面试加分):

二叉搜索树的中序遍历是有序的


3️⃣ 后序遍历(Postorder)

👉 左 → 右 → 根

scss 复制代码
function postorder(root){
  if(!root) return
  postorder(root.left)
  postorder(root.right)
  console.log(root.val)
}

📌 适合:

  • 删除节点
  • 释放资源
  • 自底向上计算

七、层序遍历:唯一的「非递归主角」

🌊 从上到下,一层一层

核心思想:队列(FIFO)

scss 复制代码
function levelOrder(root){
  if(!root) return []
  const res = []
  const queue = [root]

  while(queue.length){
    const node = queue.shift()
    res.push(node.val)
    if(node.left) queue.push(node.left)
    if(node.right) queue.push(node.right)
  }

  return res
}

📌 面试官想考你的是:

  • 你是否知道 BFS
  • 你是否能想到 队列

八、树题的"万能拆解模板"

每次看到树题,按这个流程走👇

① 明确递归函数的定义

dfs(root) 到底返回什么?


② 找重复子问题

左子树怎么做?右子树怎么做?


③ 找退出条件

root == null 时怎么办?


④ 决定「根」什么时候处理

  • 前?中?后?

📌 90% 的树题,死在第 ① 步没想清楚


九、最后:你不是不会树,是没"建模"

很多人学树失败,并不是因为代码写不出,而是:

  • ❌ 把它当"记忆题"
  • ❌ 死背遍历顺序
  • ❌ 不理解递归的意义

真正的高手,看到树只想一件事:

"这棵树,能不能拆成左右子树的重复问题?"

一旦你建立了这个视角:

  • 树不再难
  • 递归不再怕
  • 面试不再慌
相关推荐
仙俊红1 天前
LeetCode487周赛T2,删除子数组后的最终元素
数据结构·算法
2501_920931701 天前
React Native鸿蒙跨平台采用ScrollView的horizontal属性实现横向滚动实现特色游戏轮播和分类导航
javascript·react native·react.js·游戏·ecmascript·harmonyos
0思必得01 天前
[Web自动化] Selenium处理动态网页
前端·爬虫·python·selenium·自动化
-dzk-1 天前
【代码随想录】LC 59.螺旋矩阵 II
c++·线性代数·算法·矩阵·模拟
风筝在晴天搁浅1 天前
hot100 78.子集
java·算法
Jasmine_llq1 天前
《P4587 [FJOI2016] 神秘数》
算法·倍增思想·稀疏表(st 表)·前缀和数组(解决静态区间和查询·st表核心实现高效预处理和查询·预处理优化(提前计算所需信息·快速io提升大规模数据读写效率
超级大只老咪1 天前
快速进制转换
笔记·算法
东东5161 天前
智能社区管理系统的设计与实现ssm+vue
前端·javascript·vue.js·毕业设计·毕设
catino1 天前
图片、文件的预览
前端·javascript
m0_706653231 天前
C++编译期数组操作
开发语言·c++·算法