题目、重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如,输入前序遍历序列{1,2,4,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并输出它的头节点。二叉树节点的定义如下:
struct BinaryTreeNode
{
int m_nValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
}
分析
前序遍历序列的第一个数字1就是根节点的值。扫描中序遍历序列,就能确定根节点的值的位置。根据中序遍历的特点,在根节点的值1前面的3个数字都是左子树节点的值,位于1后面的数字都是右子树节点的值。
由于在中序遍历序列中,有3个数字是左子树节点的值,因此左子树公有3个左子节点。同样,在前序遍历序列中,根节点后面的3个数字就是3个左子树节点的值,再后面的所有数字都是右子树节点的值。这样我们就在前序遍历序列和中序遍历序列中分别找到了左子树、右子树对应的子序列。以此类推,接下来可以用递归的方法去完成。
完整代码
public class BuildTree {
public static void main(String[] args) {
// TODO Auto-generated method stub
BuildTree c = new BuildTree();
int[] pre = {1,2,4,7,3,5,6,8};//前序遍历序列
int[] in = {4,7,2,1,5,3,8,6};//中序遍历序列
//返回后序遍历结果
TreeNode t = c.Construct(pre,in);
System.out.println("后序遍历结果为:");
c.lastOrder(t);
}
//通过前序和中序遍历序列重建二叉树
public TreeNode Construct(int[] pre, int[] in) {
// TODO Auto-generated method stub
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]) { //遍历中序序列 in[i]
/*在中序遍历序列中查找根节点,找到根节点,
*然后可得到左子树root.left和右子树root.left
* 然后再将左子树(前序+中序)作为一个二叉树,进行中序遍历找到其中的根节点,
* 然后根据根节点得到左子树root.left和右子树root.right
* */
root.left = Construct(Arrays.copyOfRange(pre, 1,i+1),Arrays.copyOfRange(in, 0, i));
//构建子树时可以直接使用Arrays.copyOfRange(int []original,int from,int to),original为原始的int型数组,from为开始角标值,to为终止角标值。(其中包括from角标,不包括to角标。即处于[from,to)左闭右开状态
root.right = Construct(Arrays.copyOfRange(pre, i+1, pre.length),Arrays.copyOfRange(in, i+1, in.length));
}
}
return root;
}
//后序遍历结果 重建后的二叉树后序遍历方式输出二叉树
public void lastOrder(TreeNode t) {
// TODO Auto-generated method stub
if(t != null) {
lastOrder(t.left);
lastOrder(t.right);
System.out.print(t.val+" ");
}
}
}
class TreeNode{
int val;
TreeNode left;
TreeNode right;
TreeNode(int val){
this.val = val;
}
}