题目描述:输入某二叉树的前序遍历和中序遍历结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不包含重复的数字。例如输入前序遍历序列:{1,2,4,7,3,5,6,8}和中序遍历{4,7,2,1,5,3,8,6},则重建出图中所示二叉树并且输出它的头结点。
重建的二叉树:
思路:先找出根节点,然后利用递归方法构造二叉树
解法一:
package Problem6;
3 /* 重建二叉树
7 */
8 //定义二叉树节点
9 class BinaryTreeNode {
10 public int value;
11 public BinaryTreeNode leftNode;
12 public BinaryTreeNode rightNode;
14 // 无参构造函数
15 public BinaryTreeNode() {}
19 // 有参构造函数
20 public BinaryTreeNode(int value) {
21 this.value = value;
22 this.leftNode = null;
23 this.rightNode = null;
24 }
25 }
27 public class ConstructBinaryTree {
29 public static BinaryTreeNode construct(int preOrder[], int inOrder[],
30 int length) throws Exception {
31 if (preOrder == null || inOrder == null || length < 0) {
32 return null;
33 }
34 return constructCore(preOrder, 0, preOrder.length - 1, inOrder, 0,
35 inOrder.length - 1);
36 }
38 public static BinaryTreeNode constructCore(int preOrder[],
39 int startPreIndex, int endPreIndex, int inOrder[],
40 int startInIndex, int endInIndex) throws InvalidPutException {
41 // 头结点的值
42 int rootValue = preOrder[startInIndex];
44 // 构建一个只有一个根节点的二叉树
45 BinaryTreeNode root = new BinaryTreeNode(rootValue);
46 // 只有一个元素的情况下:
47 if (startPreIndex == endPreIndex) {
48 if (startInIndex == endInIndex
49 && preOrder[startInIndex] == inOrder[endInIndex]) {
50 System.out.println("只有一个元素");
51 return root;
52 } else {
53 throw new InvalidPutException();
54 }
56 }
57 // 最重要的一步:在中序遍历中找到根结点的索引
58 int rootInIndex = startInIndex;
59 while (rootInIndex <= endInIndex && inOrder[rootInIndex] != rootValue) {
60 rootInIndex++;
61 }
62 if (rootInIndex == endInIndex && inOrder[rootInIndex] != rootInIndex) {
63 throw new InvalidPutException();
64 }
65 // 根节点的左子树的长度
66 int leftLength = rootInIndex - startInIndex;
67 // 根节点的左子树的最右端的索引值
68 int leftPreEndIndex = startPreIndex + leftLength;
69 // 构建左子树
70 if (leftLength > 0) {
71 root.leftNode = constructCore(preOrder, startPreIndex + 1,
72 leftPreEndIndex, inOrder, startInIndex, rootInIndex - 1);
73 }
74 // 说明根节点存在右子树
75 if (leftLength < endPreIndex - startPreIndex) {
76 root.rightNode = constructCore(preOrder, leftPreEndIndex + 1,
77 endPreIndex, inOrder, rootInIndex + 1, endInIndex);
78 }
79 return root;
80 }
82 // 按照前序遍历打印二叉树的节点
83 public static void printPreBinaryTree(BinaryTreeNode root) {
84 if (root == null) {
85 return;
86 } else {
87 System.out.println(root.value + " ");
88 }
89 if (root.leftNode != null) {
90 printPreBinaryTree(root.leftNode);
91 }
92 if (root.rightNode != null) {
93 printPreBinaryTree(root.rightNode);
94 }
95 }
97 public static class InvalidPutException extends Exception {
99 private static final long serialVersionUID = 1L;
100 }
102 /**
103 * @param args
104 * @throws Exception
105 */
106 public static void main(String[] args) throws Exception {
107 int preOrder[] = { 1, 2, 4, 7, 3, 5, 6, 8 };
108 int inOrder[] = { 4, 7, 2, 1, 5, 3, 8, 6 };
109 ConstructBinaryTree test = new ConstructBinaryTree();
110 printPreBinaryTree(test.construct(preOrder, inOrder, preOrder.length));
111 }
113 }
解法二:借助Arrays.copyOfRange( )实现递归调用
Arrays.copyOfRange(T[ ] original,int from,int to) --> 左闭右开
将一个原始的数组original,从下标from开始复制,复制到下标to,生成一个新的数组(包括下标from,不包括下标to)
static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
if (pre == null || in == null) {
return null;
}
if (pre.length == 0 || in.length == 0) {
return null;
}
if (pre.length != in.length) {
return null;
}
TreeNode root = new TreeNode(pre[0]);
for (int i = 0; i < pre.length; i++) {
if (pre[0] == in[i]) {
root.left = reConstructBinaryTree(
Arrays.copyOfRange(pre,1,i+1),Arrays.copyOfRange(in,0,i));
root.right = reConstructBinaryTree(
Arrays.copyOfRange(pre,i+1,pre.length),Arrays.copyOfRange(in,i+1,in.length));
}
}
return root;
}