二叉树遍历
前序遍历
先访问根节点,再访问左子节点,最后访问右子节点 10,6,4,8,14,12,16
中序遍历
先访问左子节点,再访问根节点,最后访问右子节点 4,6,8,10,12,14,16
后序遍历
先访问左子节点,再访问右子节点,最后访问根节点 4,8,6,12,16,14,10
宽度优先遍历
先访问第一层节点,再访问第二层节点,一直访问到最后一层,同一层节点中,从左到右顺序依次访问 10,6,14,4,8,12,16
题目
二叉树的前序遍历序列{1,2,4,7,3,5,6,8},中序遍历结果 (4,7,2,1,5,3,8,6),重建二叉树
分析
- 由前序遍历特点可以得出 前序遍历结果第一位是根节点
- 由中序遍历特点得出 根节点左边的元素都是左子树,右边的元素都是右子树
- 左右子树拆分之后,左右子树前序遍历和中序遍历的结果也符合 1,2 两个结论
步骤
- 查询根元素 前序遍历结果
| 1 | 2 | 4 | 7 | 3 | 5 | 6 | 8 |
|---|
节点 1 是根元素
- 分拆左右子树
| 4 | 7 | 2 | 1 | 5 | 3 | 8 | 6 |
|---|
查询出根元素的位置,其左边数据是左子树节点,右边部分是右子树节点 左子树中序遍历结果 :
| 4 | 7 | 2 |
|---|
右子树中序遍历结果
| 5 | 3 | 8 | 6 |
|---|
- 查询左右子树对应的前序遍历结果
左子树中序遍历结果数据长度为3,那么前序遍历结果中 [1,3] 角标的数据是左子树前序遍历结果
| 2 | 4 | 7 |
|---|
右子树前序遍历结果的角标是在左子树结果之后的四个元素,右子树前序遍历结果为
| 3 | 5 | 6 | 8 |
|---|
- 左右子树再继续递归处理
代码实现
public class RebuildTree {
public static void main(String[] args) {
int[] preArray = new int[]{1, 2, 4, 7, 3, 5, 6, 8};
int[] inArray = new int[]{4, 7, 2, 1, 5, 3, 8, 6};
Node node = rebuildNode(preArray, 0, preArray.length - 1, inArray, 0, inArray.length - 1);
System.out.println(JSONObject.toJSONString(node));
}
/**
* @param preArray 前序遍历结果
* @param preStartIndex 重建二叉树前序遍历结果开始角标
* @param preEndIndex 重建二叉树前序遍历结果结束角标
* @param inArray 中序遍历结果
* @param inStartIndex 重建二叉树中序遍历结果开始角标
* @param inEndIndex 重建二叉树中序遍历结果结束角标
* @return
*/
private static Node rebuildNode(int[] preArray, int preStartIndex, int preEndIndex, int[] inArray, int inStartIndex, int inEndIndex) {
if (Objects.isNull(preArray) || Objects.isNull(inArray) || preArray.length != inArray.length) {
throw new RuntimeException("输入信息错误");
}
if (preStartIndex > preEndIndex) {
return null;
}
int rootValue = preArray[preStartIndex];
int rootAtInArrayIndex = inStartIndex;
while (rootValue != inArray[rootAtInArrayIndex]) {
rootAtInArrayIndex++;
}
if (rootValue != inArray[rootAtInArrayIndex]) {
throw new RuntimeException("中序遍历结果没有查询到根节点");
}
Node node = new Node();
node.setValue(rootValue);
Node leftNode = rebuildNode(preArray, preStartIndex + 1, preStartIndex + (rootAtInArrayIndex - inStartIndex), inArray, inStartIndex, rootAtInArrayIndex - 1);
Node rigthNode = rebuildNode(preArray, preStartIndex + (rootAtInArrayIndex - inStartIndex) + 1, preEndIndex, inArray, rootAtInArrayIndex + 1, inEndIndex);
node.setLeft(leftNode);
node.setRight(rigthNode);
return node;
}
@Data
private static class Node {
private int value;
private Node left;
private Node right;
}
}