如果数组是算法世界的地基
那么「树」,就是贯穿整个面试的 承重结构
无论你刷的是 力扣 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% 的树题,死在第 ① 步没想清楚
九、最后:你不是不会树,是没"建模"
很多人学树失败,并不是因为代码写不出,而是:
- ❌ 把它当"记忆题"
- ❌ 死背遍历顺序
- ❌ 不理解递归的意义
真正的高手,看到树只想一件事:
"这棵树,能不能拆成左右子树的重复问题?"
一旦你建立了这个视角:
- 树不再难
- 递归不再怕
- 面试不再慌