重建二叉树
题目:输入某二叉树的前序遍历和中序遍历结果,请重建此二叉树,假设输入的前序遍历和中序编列结果中都不含有重复数字.
例子:前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建如图所示都二叉树,并输出它的头节点
先来简单了解下数学定义,不清楚的小伙伴可以点接文字链接查看百度百科相关定义,这里不做缀述。
点击 前序遍历:根->左子树->右子树;
点击 中序遍历:左子树->根->右子树;
如上图所示,通过 前序遍历的定义可知:此序列的第一位即为根节点,那么通过中序遍历结合前序遍历,可以得到根节点下标左侧即为左子树,根节点下标右侧即为右子树。 那么查找中序遍历集合的根节点下标,切割左右子树集合,同一个二叉树的左右子树的节单数量是一致的,所以前序遍历集合,也依据根节点下标做分割。如此递归循环,即可成功重建此二叉树。先做准备工作,上代码。
public static BinaryTree rebuildTree(int[] preorder, int[] inorder) {
//常规判空
if (preorder == null || inorder == null) {
return null;
}
if (preorder.length == 0 || inorder.length == 0) {
return null;
}
//前序遍历序列第一位即为根节点
BinaryTree root = new BinaryTree(preorder[0]);
for (int i = 0; i < inorder.length; i++) {
//此时的i即为根节点的下标
if (inorder[i] == preorder[0]) {
//不断分割数组,递归循环调用
root.setLeftNode(rebuildTree(Arrays.copyOfRange(preorder, 1, i+1), Arrays.copyOfRange(inorder, 0, i)));
root.setRightNode(rebuildTree(Arrays.copyOfRange(preorder, i + 1, preorder.length ), Arrays.copyOfRange(inorder, i + 1, inorder.length)));
break;
}
}
return root;
}
前期准备工作
定义一个简单的树状结构,定义构造函数。并实现前序和中序遍历过程。以及准备对应的测试数据。
public class BinaryTree {
private int val;
private BinaryTree leftNode;
private BinaryTree rightNode;
//构造函数
public BinaryTree(int val) {
this.val = val;
}
//构造函数
public BinaryTree(int val, BinaryTree leftNode, BinaryTree rightNode) {
this.leftNode = leftNode;
this.rightNode = rightNode;
this.val = val;
}
public void setLeftNode(BinaryTree leftNode) {
this.leftNode = leftNode;
}
public void setRightNode(BinaryTree rightNode) {
this.rightNode = rightNode;
}
public BinaryTree getLeftNode() {
return this.leftNode;
}
public BinaryTree getRightNode() {
return this.rightNode;
}
public int getVal() {
return this.val;
}
}
先通过递归实现简单的前序遍历和中序遍历,以便后续测试验证使用。
//前序遍历
public static void preOrderSearch(BinaryTree root) {
if (root == null) {
return;
}
System.out.println(root.getVal());
preOrderSearch(root.getLeftNode());
preOrderSearch(root.getRightNode());
}
//中序遍历
public static void inOrderSearch(BinaryTree root) {
if (root == null) {
return;
}
inOrderSearch(root.getLeftNode());
System.out.println(root.getVal());
inOrderSearch(root.getRightNode());
}
最后附上测试用例,感兴趣的小伙伴可以来一块试试,另外还有一个复杂的 后序遍历,可以自行挑战实现一下。感谢大家观看。
public static void main(String[] args) {
//测试数据
BinaryTree node4l = new BinaryTree(8);
BinaryTree node4r = new BinaryTree(7);
BinaryTree node3l = new BinaryTree(4, null, node4r);
BinaryTree node3r = new BinaryTree(6, node4l, null);
BinaryTree node3l1 = new BinaryTree(5);
BinaryTree node2l = new BinaryTree(2, node3l, null);
BinaryTree node2r = new BinaryTree(3, node3l1, node3r);
BinaryTree node = new BinaryTree(1, node2l, node2r);
//验证前序遍历和中序遍历
// RebuildTree.preOrderSearch(node);
// RebuildTree.inOrderSearch(node);
int preOrder[] = new int[]{1, 2, 4, 7, 3, 5, 6, 8};
int inOrder[] = new int[]{4, 7, 2, 1, 5, 3, 6, 8};
//验证重建二叉树代码
BinaryTree root = RebuildTree.rebuildTree(preOrder,inOrder);
RebuildTree.preOrderSearch(root);
RebuildTree.inOrderSearch(root);
}