1、题目
很简单,知道一棵二叉树的前序和中序,要求重建此二叉树。
2、思路
由前序可知道根结点的值,然后遍历中序,可以找到根结点的位置,然后在该位置的左边就是根结点的左子树,右边就是右子树,然后通过递归就可以得到整棵树。
3、实现代码
/**
* decription: 树节点
* @author : linjq
*/
private class TreeNode {
private int element;
private TreeNode left;
private TreeNode right;
public TreeNode(int element) {
this.element = element;
}
}
/**
* decription: 重构二叉树,知道前序和中序 解决思路:由前序可知道一个树结点的值,然后在中序那里找到那个值,记录位置,它左边的是它的
* 左子树,右边是右子树,依次递归可得到整棵树。
* @author : linjq
*/
private TreeNode rebuidTree(int[] preOrder, int[] inOrder, int preBegin,
int preEnd, int inBegin, int inEnd) {
if (preBegin > preEnd || inBegin > inEnd) {
return null; // 证明已到尽头,返回空结点
} else {
TreeNode rootNode = new TreeNode(preOrder[preBegin]);
// 当前节点值在中序的位置,找到该位置是为了找到这个结点的左右子树
int rootInPosition = -1;
for (int i = inBegin; i <= inEnd; i++) {
if (inOrder[i] == rootNode.element) {
rootInPosition = i;
break;
}
}
//下面是准确定位到哪些是它的左子树范围,哪些事右子树
int leftNum = rootInPosition - inBegin;// 左子树 有多少个结点
int leftPreBegin = preBegin + 1;
int leftPreEnd = preBegin + leftNum;
int leftInBegin = inBegin;
int leftInEnd = inBegin + leftNum;
int rightPreBegin = preBegin + 1 + leftNum;
int rightPreEnd = preEnd;
int rightInBegin = rootInPosition + 1;
int rightInEnd = inEnd;
// 寻找该结点的左子树,右子树
TreeNode leftNode = rebuidTree(preOrder, inOrder, leftPreBegin,
leftPreEnd, leftInBegin, leftInEnd);
TreeNode righNode = rebuidTree(preOrder, inOrder, rightPreBegin,
rightPreEnd, rightInBegin, rightInEnd);
rootNode.left = leftNode;
rootNode.right = righNode;
return rootNode;
}
}
/**
* decription:中序遍历
* @author : linjq
*/
public void inOrder(TreeNode rootNode) {
if (rootNode == null) {
return;
} else {
inOrder(rootNode.left);
System.out.print(rootNode.element + " ");
inOrder(rootNode.right);
}
}
/**
* decription:前序遍历
* @author : linjq
*/
public void preOrder(TreeNode rootNode) {
if (rootNode == null) {
return;
} else {
System.out.print(rootNode.element + " ");
preOrder(rootNode.left);
preOrder(rootNode.right);
}
}
/**
* decription: main方法 测试 重建二叉树
* @author : linjq
*/
public static void main(String[] args) {
RecoverBST bst = new RecoverBST();
int[] inOrder = {4,7,2,1,5,3,8,6};
int[] preOrder = {1,2,4,7,3,5,6,8};
TreeNode root = bst.rebuidTree(preOrder, inOrder, 0, preOrder.length-1, 0, inOrder.length-1);
System.out.println("重建后的中序");
//输出中序
bst.inOrder(root);
System.out.println();
System.out.println("重建后的前序");
//输出前序
bst.preOrder(root);
}
4、测试结果
对比给定的已知条件,它们一致,代码正确。然而,递归的方法虽然简单,当该二叉树很深很深,比如深度达到1000以上的时候,用递归就不好了,容易造成栈溢出。因此,换成非递归方法来实现是更好的选择。