一、树的基础概念
树是一种分层结构的非线性数据结构,像家谱、公司组织架构、文件目录都是树状结构。 一个“树”至少有一个节点,这个节点叫做根节点(root),其下可以有很多子节点(children),每个子节点又可能有自己的子节点…
树的术语
| 名称 | 说明 |
|---|---|
| 根节点 | 树的最上面那个节点 |
| 子节点 | 根节点的子分支节点 |
| 叶子节点 | 没有子节点的节点 |
| 父节点 | 某个子节点的上一级节点 |
| 深度 | 从根节点到该节点的路径长度 |
| 高度 | 从该节点到叶子节点最长路径长度 |
二、二叉树(Binary Tree)
什么是二叉树?
每个节点最多有两个子节点(左子树、右子树),就是二叉树。
1
/ \
2 3
/ \
4 5
JS 中二叉树结构(基础写法):
class TreeNode {
constructor(val) {
this.val = val;
this.left = null;
this.right = null;
}
}
三、二叉搜索树(BST)
什么是 BST?
二叉搜索树是一种特殊的二叉树,满足:
- 左子树所有节点 < 根节点
- 右子树所有节点 > 根节点
- 每棵子树也都是 BST
5
/ \
3 7
/ \ \
2 4 9
四、遍历方式
按顺序访问每个节点
遍历二叉树分为:
1、前序遍历(根→左→右)
function preOrder(root) {
if (!root) return;
console.log(root.value);
preOrder(root.left);
preOrder(root.right);
}
2、中序遍历(左→根→右)
function inOrder(root) {
if (!root) return;
inOrder(root.left);
console.log(root.value);
inOrder(root.right);
}
3、后序遍历(左→右→根)
function postOrder(root) {
if (!root) return;
postOrder(root.left);
postOrder(root.right);
console.log(root.value);
}
4、层序遍历(Level Order Traversal)函数,也叫广度优先遍历,(从上到下,从左到右)➡️ 借助队列
function levelOrder(node) {
if(!root) return;
const queue = [root];
while(queue.length) {
const node = queue.shift();
console.log(node.value);
if(node.left) queue.push(left);
if(node.right) queue.push(right);
}
}
五、经典二叉树题目(LeetCode高频)
1. 最大深度(递归)
function maxDepth(root) {
if (!root) return 0;
return 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
}
2. 路径总和(是否存在一条路径从根到叶子,和为 target)
function hasSumPath(root, target) {
if (!root) return false;
if (!root.left && !root.right) return root.val === target;
return (
hasSumPath(root.left, target - root.val) ||
hasSumPath(root.right, target - root.val)
);
}
3. 平衡二叉树(左右子树高度差不超过 1)
一棵二叉树是“平衡的”,指的是:
对于每个节点,它的左子树和右子树的高度差不超过 1,并且左右子树本身也是平衡的。
平衡的例子 ✅:
1
/ \
2 3
/
4
每一层的计算如下:
- 节点 4:左右都是 null,高度为 0 → 返回 1
- 节点 2:左边是 1,右边是 0,差值 1 → 返回 2
- 节点 3:左右都是 null → 返回 1
- 节点 1:左是 2,右是 1,差值 1 → 返回 3
最终返回 ≠ -1,所以是平衡
不平衡的例子 ❌:
1
/
2
/
3
- 节点 3:返回 1
- 节点 2:左边是 1,右边是 0 → 高度 2
- 节点 1:左边是 2,右边是 0 → 差值 2 ❌ → 返回 -1
所以最终 height(root) === -1,函数返回 false,代表不平衡。
代码如下:
function isBalanced(root) {
function height(node) {
if (!node) return 0;
const left = height(node.left);
const right = height(node.right);
if (left === -1 || right === -1 || Math.abs(left - right) > 1) return -1;
return Math.max(left, right) + 1;
}
return height(root) !== -1;
}