引言
树是非线性数据结构中最重要的一种,二叉树更是面试高频考点。本文系统讲解树的核心概念和经典算法,帮助你全面掌握树数据结构。
一、树的基本概念
1.1 树的定义
1 2 3 4 5 6 7 8 9 10
| public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int val) { this.val = val; } }
|
1.2 树的术语
- 根节点:树的顶部节点
- 叶子节点:没有子节点的节点
- 高度:节点到叶子节点的最长路径
- 深度:节点到根节点的路径长度
- 层:根节点为第1层
二、二叉树遍历
2.1 前序遍历(根-左-右)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public void preorder(TreeNode root) { if (root == null) return; System.out.print(root.val + " "); preorder(root.left); preorder(root.right); }
public List<Integer> preorderIterative(TreeNode root) { List<Integer> result = new ArrayList<>(); if (root == null) return result; Stack<TreeNode> stack = new Stack<>(); stack.push(root); while (!stack.isEmpty()) { TreeNode node = stack.pop(); result.add(node.val); if (node.right != null) stack.push(node.right); if (node.left != null) stack.push(node.left); } return result; }
|
2.2 中序遍历(左-根-右)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public void inorder(TreeNode root) { if (root == null) return; inorder(root.left); System.out.print(root.val + " "); inorder(root.right); }
public List<Integer> inorderIterative(TreeNode root) { List<Integer> result = new ArrayList<>(); Stack<TreeNode> stack = new Stack<>(); TreeNode curr = root; while (curr != null || !stack.isEmpty()) { while (curr != null) { stack.push(curr); curr = curr.left; } curr = stack.pop(); result.add(curr.val); curr = curr.right; } return result; }
|
2.3 后序遍历(左-右-根)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public void postorder(TreeNode root) { if (root == null) return; postorder(root.left); postorder(root.right); System.out.print(root.val + " "); }
public List<Integer> postorderIterative(TreeNode root) { LinkedList<Integer> result = new LinkedList<>(); if (root == null) return result; Stack<TreeNode> stack = new Stack<>(); stack.push(root); while (!stack.isEmpty()) { TreeNode node = stack.pop(); result.addFirst(node.val); if (node.left != null) stack.push(node.left); if (node.right != null) stack.push(node.right); } return result; }
|
2.4 层序遍历(BFS)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public List<List<Integer>> levelOrder(TreeNode root) { List<List<Integer>> result = new ArrayList<>(); if (root == null) return result; Queue<TreeNode> queue = new LinkedList<>(); queue.offer(root); while (!queue.isEmpty()) { int size = queue.size(); List<Integer> level = new ArrayList<>(); for (int i = 0; i < size; i++) { TreeNode node = queue.poll(); level.add(node.val); if (node.left != null) queue.offer(node.left); if (node.right != null) queue.offer(node.right); } result.add(level); } return result; }
|
三、二叉树经典题目
3.1 最大深度(LeetCode 104)
1 2 3 4
| public int maxDepth(TreeNode root) { if (root == null) return 0; return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1; }
|
3.2 翻转二叉树(LeetCode 226)
1 2 3 4 5 6 7 8 9
| public TreeNode invertTree(TreeNode root) { if (root == null) return null; TreeNode temp = root.left; root.left = invertTree(root.right); root.right = invertTree(temp); return root; }
|
3.3 对称二叉树(LeetCode 101)
1 2 3 4 5 6 7 8 9 10 11 12
| public boolean isSymmetric(TreeNode root) { return isMirror(root, root); }
private boolean isMirror(TreeNode t1, TreeNode t2) { if (t1 == null && t2 == null) return true; if (t1 == null || t2 == null) return false; return t1.val == t2.val && isMirror(t1.left, t2.right) && isMirror(t1.right, t2.left); }
|
3.4 路径总和(LeetCode 112)
1 2 3 4 5 6 7 8 9 10
| public boolean hasPathSum(TreeNode root, int targetSum) { if (root == null) return false; if (root.left == null && root.right == null) { return root.val == targetSum; } return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val); }
|
3.5 最近公共祖先(LeetCode 236)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if (root == null || root == p || root == q) { return root; } TreeNode left = lowestCommonAncestor(root.left, p, q); TreeNode right = lowestCommonAncestor(root.right, p, q); if (left != null && right != null) { return root; } return left != null ? left : right; }
|
四、二叉搜索树
4.1 BST性质
- 左子树所有节点 < 根节点
- 右子树所有节点 > 根节点
- 左右子树也是BST
- 中序遍历结果有序
4.2 BST插入
1 2 3 4 5 6 7 8 9 10 11 12 13
| public TreeNode insertIntoBST(TreeNode root, int val) { if (root == null) { return new TreeNode(val); } if (val < root.val) { root.left = insertIntoBST(root.left, val); } else { root.right = insertIntoBST(root.right, val); } return root; }
|
4.3 BST删除
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| public TreeNode deleteNode(TreeNode root, int key) { if (root == null) return null; if (key < root.val) { root.left = deleteNode(root.left, key); } else if (key > root.val) { root.right = deleteNode(root.right, key); } else { if (root.left == null) return root.right; if (root.right == null) return root.left; TreeNode minNode = findMin(root.right); root.val = minNode.val; root.right = deleteNode(root.right, minNode.val); } return root; }
private TreeNode findMin(TreeNode node) { while (node.left != null) { node = node.left; } return node; }
|
4.4 验证BST(LeetCode 98)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public boolean isValidBST(TreeNode root) { return isValid(root, null, null); }
private boolean isValid(TreeNode node, Integer min, Integer max) { if (node == null) return true; if ((min != null && node.val <= min) || (max != null && node.val >= max)) { return false; } return isValid(node.left, min, node.val) && isValid(node.right, node.val, max); }
|
五、平衡二叉树(AVL树)
5.1 AVL树定义
任意节点的左右子树高度差不超过1
5.2 旋转操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| private TreeNode leftRotate(TreeNode node) { TreeNode newRoot = node.right; node.right = newRoot.left; newRoot.left = node; updateHeight(node); updateHeight(newRoot); return newRoot; }
private TreeNode rightRotate(TreeNode node) { TreeNode newRoot = node.left; node.left = newRoot.right; newRoot.right = node; updateHeight(node); updateHeight(newRoot); return newRoot; }
|
六、复杂度分析
| 操作 |
平均 |
最坏 |
| 搜索 |
O(log n) |
O(n) |
| 插入 |
O(log n) |
O(n) |
| 删除 |
O(log n) |
O(n) |
| 遍历 |
O(n) |
O(n) |
总结
树算法核心:
- 遍历:前中后序、层序
- BST:插入、删除、验证
- 递归:大部分树问题的解法
- 平衡树:AVL、红黑树
参考资料