CS61B
课程笔记(Examprep 10 Heaps and Graphs Exam Prep)
1. 操作理解(An
Operational Understanding)
1.1 二叉搜索树(BST)的性质
在二叉搜索树中,左子树的所有节点的值都小于根节点的值,右子树的所有节点的值都大于根节点的值。对于给定树中的希腊字母代表的数字值,需要对可能符合条件的值进行阴影处理。
2. Xelha树(Xelha Trees)
2.1 定义和性质
Xelha树是一种特殊的树,具有以下性质:
- 最小堆性质:每个节点的值都小于或等于其子节点的值。
- 中序遍历:Xelha树的中序遍历与输入的数字列表顺序相同。
2.2 有效的Xelha树
确定以下给定序列是否为有效的Xelha树。第一个例子已经完成。
画出对应于序列\(8, 3, 9,
1\)的有效Xelha树。
2.3 验证Xelha树的函数
下面的代码定义了一个函数validXelhaTree
,用于验证给定的IntTree
是否是对应于指定列表的有效Xelha树。
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 28 29 30 31
| public class TestXelhaTree { public static class IntTree { public int item; public IntTree left, right; }
public static boolean validXelhaTree(IntTree xt, List<Integer> vals) { List<Integer> treeValues = new ArrayList<Integer>(); getTreeValues(xt, treeValues); return isAHeap(xt) && treeValues.equals(vals); }
private static void getTreeValues(IntTree xt, List<Integer> treeValues) { if (xt == null) return; getTreeValues(xt.left, treeValues); treeValues.add(xt.item); getTreeValues(xt.right, treeValues); }
public static boolean isAHeap(IntTree xt) { if (xt == null) return true; if (xt.item > getItem(xt.left)) return false; if (xt.item > getItem(xt.right)) return false; return isAHeap(xt.left) && isAHeap(xt.right); }
private static int getItem(IntTree x) { if (x == null) return Integer.MAX_VALUE; return x.item; } }
|
3.
从遍历重建树(Reconstructing Trees from Traversals)
3.1 重建二叉树的思路
给定两个整数列表,一个表示二叉树的前序遍历,另一个表示中序遍历。可以通过以下步骤重建二叉树:
- 识别根节点:前序遍历的第一个元素是根节点。
- 分割中序遍历:在中序遍历中找到根节点的位置,确定左子树和右子树的节点。
- 构建子树:根据左子树的节点数量,从前序遍历中提取相应的子列表,递归构建左子树和右子树。
3.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 27 28 29 30 31 32 33
| public IntTree constructTree(int[] preorder, int[] inorder) { if (preorder.length == 0) return null; int rootValue = preorder[0]; IntTree root = new IntTree(); root.item = rootValue;
int rootIndex = findIndex(inorder, rootValue);
int[] leftInorder = Arrays.copyOfRange(inorder, 0, rootIndex); int[] rightInorder = Arrays.copyOfRange(inorder, rootIndex + 1, inorder.length);
int[] leftPreorder = Arrays.copyOfRange(preorder, 1, leftInorder.length + 1); int[] rightPreorder = Arrays.copyOfRange(preorder, leftInorder.length + 1, preorder.length);
root.left = constructTree(leftPreorder, leftInorder); root.right = constructTree(rightPreorder, rightInorder);
return root; }
private int findIndex(int[] inorder, int value) { for (int i = 0; i < inorder.length; i++) { if (inorder[i] == value) { return i; } } return -1; }
|
重建二叉树的题目是LeetCode上的一道经典题目。
题目描述
给定两个整数数组 preorder
和 inorder
,其中:
preorder
是二叉树的前序遍历数组。
inorder
是二叉树的中序遍历数组。
请你构造并返回这棵树的根节点。
示例
示例 1
1 2
| 输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7] 输出: [3,9,20,null,null,15,7]
|
示例 2
1 2
| 输入: preorder = [-1], inorder = [-1] 输出: [-1]
|
示例 3
1 2
| 输入: [], inorder = [] 输出: []
|
解题思路
- 前序遍历特点:前序遍历的第一个元素是树的根节点。
- 中序遍历特点:在中序遍历中,根节点左边的元素是左子树,右边的元素是右子树。
- 递归构建:
- 从前序数组中取出根节点,找到该根节点在中序数组中的索引。
- 利用该索引划分中序数组为左子树和右子树。
- 根据划分出的左子树和右子树的节点数量,从前序数组中提取对应的节点。
- 递归构建左右子树。