树与二叉树完全解析:从基础到应用
目录
一、树形结构的基础认知
1.1 树的定义与特点
1.2 核心术语解析
二、二叉树的深度解析
2.1 二叉树定义
2.2 特殊二叉树类型
2.3 重要性质总结
三、二叉树的存储与遍历
3.1 存储方式对比
3.2 遍历算法精讲
四、经典题型训练
4.1 相同树判断(LeetCode 100)
4.2 子树判断(LeetCode 572)
4.3 平衡二叉树判断(LeetCode 110)
4.4 翻转二叉树(LeetCode 226)
4.5 对称二叉树(LeetCode 101)
一、树形结构的基础认知
1.1 树的定义与特点
树是一种非线性数据结构,由有限节点组成层次关系集合。核心特点:
- 唯一根节点:没有父节点的起始点
- 分层结构:每个节点都是子树的根
- 隔离原则:子树互不相交(否则形成图结构)
1.2 核心术语解析
术语 | 说明 | 示例图示意 |
---|---|---|
结点的度 | 结点的子节点数量 | A的度为3 |
叶子结点 | 度为0的末端节点 | H、I、J等 |
树的度 | 树中所有结点度的最大值 | 示例树的度为3 |
层次 | 根为第1层,向下逐层递增 | 根→子→孙 |
二、二叉树的深度解析
2.1 二叉树定义
每个结点最多有两个子节点的树结构,严格区分左子树和右子树。
2.2 特殊二叉树类型
-
满二叉树
- 每层结点数达到最大值
- 深度为k时,总结点数=2^k -1
- 示例:深度3的满二叉树有7个结点
-
完全二叉树
- 除最后一层外全满
- 最后一层结点左对齐
- 应用场景:堆结构实现
2.3 重要性质总结
-
叶子结点公式:n0 = n2 + 1
(叶子结点数=度为2的结点数+1) -
结点与深度关系:
- 最大结点数:2^k -1
- 完全二叉树深度:⌈log₂(n+1)⌉
-
顺序存储特性(数组表示):
- 父结点索引:(i-1)/2
- 左子结点:2i+1
- 右子结点:2i+2
三、二叉树的存储与遍历
3.1 存储方式对比
存储方式 | 优点 | 缺点 |
---|---|---|
顺序存储 | 访问速度快 | 适合完全二叉树 |
链式存储 | 灵活处理任意结构 | 需要额外指针空间 |
链式存储代码实现:
class TreeNode {int val;TreeNode left;TreeNode right;public TreeNode(int val) {this.val = val;}
}
3.2 遍历算法精讲
递归遍历三件套:
// 前序遍历
void preOrder(TreeNode root) {if (root == null) return;System.out.print(root.val + " ");preOrder(root.left);preOrder(root.right);
}// 中序遍历
void inOrder(TreeNode root) {if (root == null) return;inOrder(root.left);System.out.print(root.val + " ");inOrder(root.right);
}// 后序遍历
void postOrder(TreeNode root) {if (root == null) return;postOrder(root.left);postOrder(root.right);System.out.print(root.val + " ");
}
非递归遍历技巧:
// 前序遍历(栈实现)
void preOrderStack(TreeNode root) {Stack<TreeNode> stack = new Stack<>();TreeNode cur = root;while (cur != null || !stack.isEmpty()) {while (cur != null) {System.out.print(cur.val + " ");stack.push(cur);cur = cur.left;}cur = stack.pop().right;}
}
层序遍历(队列实现):
void levelOrder(TreeNode root) {Queue<TreeNode> queue = new LinkedList<>();if (root != null) queue.offer(root);while (!queue.isEmpty()) {TreeNode node = queue.poll();System.out.print(node.val + " ");if (node.left != null) queue.offer(node.left);if (node.right != null) queue.offer(node.right);}
}
四、经典题型训练
4.1 相同树判断(LeetCode 100)
问题描述:判断两棵树结构和值是否完全相同。
递归解法:
public boolean isSameTree(TreeNode p, TreeNode q) {// 结构判断if (p == null && q == null) return true;if (p == null || q == null) return false;// 值判断 + 递归验证子树return p.val == q.val && isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
}
4.2 子树判断(LeetCode 572)
解题思路:双重递归验证
public boolean isSubtree(TreeNode root, TreeNode subRoot) {if (root == null) return false;return isSame(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot);
}private boolean isSame(TreeNode a, TreeNode b) {if (a == null && b == null) return true;if (a == null || b == null) return false;return a.val == b.val && isSame(a.left, b.left) && isSame(a.right, b.right);
}
4.3 平衡二叉树判断(LeetCode 110)
优化解法(时间复杂度O(n)):
public boolean isBalanced(TreeNode root) {return height(root) != -1;
}private int height(TreeNode root) {if (root == null) return 0;int left = height(root.left);if (left == -1) return -1;int right = height(root.right);if (right == -1 || Math.abs(left - right) > 1) return -1;return Math.max(left, right) + 1;
}
4.4 翻转二叉树(LeetCode 226)
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;
}
4.5 对称二叉树(LeetCode 101)
public boolean isSymmetric(TreeNode root) {return root == null || checkSymmetry(root.left, root.right);
}private boolean checkSymmetry(TreeNode left, TreeNode right) {if (left == null && right == null) return true;if (left == null || right == null) return false;return left.val == right.val && checkSymmetry(left.left, right.right) && checkSymmetry(left.right, right.left);
}