剑指Offer(Java版):重建二叉树

题目:输入某二叉树的前序遍历和中序遍历的结果,请从新构造出该二叉树。假设输入的前序遍历和中序遍历的结果中不包含重复的数字。例如输入的前序遍 历序列为{1,2,4,7,3,5,6,8}和中序遍历为{4,7,2,1,5,3,6,8},则重建出二叉树并输出它的头结点。数组

在二叉树的前序遍历序列中,第一个数字老是树的根节点的值。但在中序遍历中,根节点的值在序列的中间,左子树的结点的值位于根节点的值的左边,而右子树的结点的值位于根节点的右边。所以咱们须要扫描中序遍历序列,才能找到根节点的值。this

如图所示,前序遍历序列的第一个数字1就是根节点的值。扫描中序遍历序列,就能肯定根节点的值的位置。根据中序遍历的特色,在根节点的值1前面3个数字都是左子树结点的值,位于1后面的数字都是右子树结点的值。.net

因为中序遍历序列中,有3个数字是左子树结点的值,所以左子树总共有 3个左子结点。一样,在前序遍历的序列中,根节点后面的3个数字就是3个左子树结点的值,再后面的全部数字都是右子树结点的值。这样咱们就在前序遍历和中 序遍历两个序列中,分别找到了左右子树对应的子序列。指针

既然咱们已经分别找到了左、右子树的前序遍历序列和中序遍历序列,咱们能够用一样的方法分别去构建左右子树。也就是说,接下来的事情能够用递归的方法去完成。递归

咱们使用Java语言来实现上面的代码:索引

package cglib;get

 

class BinaryTreeNode {  
    public int value;  
    public BinaryTreeNode leftNode;  
    public BinaryTreeNode rightNode;  
      
    public BinaryTreeNode(){  
          
    }  
    public BinaryTreeNode(int value){  
        this.value = value ;  
        this.leftNode = null;  
        this.rightNode = null;  
    }  
      
}   
public class List1  
{  
    /**  
     *   
     * @param preOrder 前序遍历数组  
     * @param inOrder 中序遍历数组  
     * @param length 数组长度  
     * @return 根结点  
     */  
    public static BinaryTreeNode Construct(int[] preOrder, int[] inOrder,int length){  
        if (preOrder == null || inOrder == null || length <= 0) {  
            System.out.println("空指针");  
            return null;  
        }  
        try {  
            return ConstructCore(preOrder, 0, preOrder.length - 1, inOrder, 0,inOrder.length - 1);  
        } catch (InvalidPutException e) {  
            e.printStackTrace();  
            return null;  
        }  
    }  
 
    /**  
     *   
     * @param PreOrder  
     *            前序遍历序列  
     * @param startPreIndex  
     *            前序序列开始位置  
     * @param endPreIndex  
     *            前序序列结束位置  
     * @param InOrder  
     *            中序遍历序列  
     * @param startInIndex  
     *            中序序列开始位置  
     * @param endInIndex  
     *            中序序列结束位置  
     * @return 根结点  
     * @throws InvalidPutException  
     */  
    public static BinaryTreeNode ConstructCore(int[] preOrder,int startPreIndex, int endPreIndex,   
            int[] inOrder,int startInIndex, int endInIndex) throws InvalidPutException {  
 
        int rootValue = preOrder[startPreIndex]; // startPreIndex=0
        System.out.println("根节点值:rootValue = " + rootValue);  
        BinaryTreeNode root = new BinaryTreeNode(rootValue);  
 
        // 只有一个元素  
        if (startPreIndex == endPreIndex) {
            System.out.println("前序的开始和结束位置相等");
            System.out.println("startPreIndex="+startPreIndex);
            System.out.println("endPreIndex="+endPreIndex);
            System.out.println("preOrder[startPreIndex]="+preOrder[startPreIndex]);
            System.out.println("inOrder[startInIndex]="+inOrder[startInIndex]);
            System.out.println("startInIndex="+startInIndex);
            System.out.println("endInIndex="+endInIndex);
            if (startInIndex == endInIndex  
                    && preOrder[startPreIndex] == inOrder[startInIndex]) {  
                
                System.out.println("中序开始位置等于中序结束位置,而且前序开始位置之值等于中序开始位置之值,返回root="+root);  
                return root;  
            } else {
                System.out.println("抛出异常");
                throw new InvalidPutException();  
            }  
        }  
 
        // 在中序遍历中找到根结点的索引
        System.out.println("在中序遍历中找根结点的索引");
        int rootInIndex = startInIndex; // startInIndex=0,根节点索引在前序组中是0
 
        while (rootInIndex <= endInIndex && inOrder[rootInIndex] != rootValue) {  
            System.out.println("还没找到,自增");
            ++rootInIndex;
            System.out.println("rootInIndex="+rootInIndex);
        }  
 
        if (rootInIndex == endInIndex && inOrder[rootInIndex] != rootValue) {  
            System.out.println("索引到底了,值不一样抛出异常");
            throw new InvalidPutException();  
 
        }  
 
        int leftLength = rootInIndex - startInIndex; // rootInIndex=3,序号;startInIndex=0;左子树长度是3,有3个元素
 
        int leftPreOrderEndIndex = startPreIndex + leftLength;  //前序里面的左子树1->2,4,7,结束到7,索引号为3
 
        if (leftLength > 0) {  
            // 构建左子树  
            root.leftNode = ConstructCore(preOrder, startPreIndex + 1,  
                    leftPreOrderEndIndex, inOrder, startInIndex,  
                    rootInIndex - 1); //4,7,2<-1
        }  
 
        if (leftLength < endPreIndex - startPreIndex) {  
            // 右子树有元素,构建右子树  
            root.rightNode = ConstructCore(preOrder, leftPreOrderEndIndex + 1, //1,2,4,7,3,5,6,8 从3开始,序号是4
                    endPreIndex, inOrder, rootInIndex + 1, endInIndex);  
        }  //1->5,3,8,6
        return root;  
    }  
 
    static class InvalidPutException extends Exception {  
 
        private static final long serialVersionUID = 1L;  
 
    }  
 
    public static void printPreOrder(BinaryTreeNode root) {  
        if (root == null) {  
            return;  
        } else {  
            System.out.print(root.value + " ");  
        }  
 
        if (root.leftNode != null) {  
            printPreOrder(root.leftNode);  
        }  
 
        if (root.rightNode != null) {  
            printPreOrder(root.rightNode);  
        }  
    }  
 
    public static void main(String[] args) throws Exception{  
        List1 test=new List1();  
        int[] preOrder={1,2,4,7,3,5,6,8};
        //int[] preOrder={1,2,4,7,3,5,6,9};
        int[] inOrder={4,7,2,1,5,3,8,6};  
         printPreOrder(Construct(preOrder, inOrder, preOrder.length));  
    }
io

输出:class

根节点值:rootValue = 1
在中序遍历中找根结点的索引
还没找到,自增
rootInIndex=1
还没找到,自增
rootInIndex=2
还没找到,自增
rootInIndex=3
根节点值:rootValue = 2
在中序遍历中找根结点的索引
还没找到,自增
rootInIndex=1
还没找到,自增
rootInIndex=2
根节点值:rootValue = 4
在中序遍历中找根结点的索引
根节点值:rootValue = 7
前序的开始和结束位置相等
startPreIndex=3
endPreIndex=3
preOrder[startPreIndex]=7
inOrder[startInIndex]=7
startInIndex=1
endInIndex=1
中序开始位置等于中序结束位置,而且前序开始位置之值等于中序开始位置之值,返回root=cglib.BinaryTreeNode@139a55
根节点值:rootValue = 3
在中序遍历中找根结点的索引
还没找到,自增
rootInIndex=5
根节点值:rootValue = 5
前序的开始和结束位置相等
startPreIndex=5
endPreIndex=5
preOrder[startPreIndex]=5
inOrder[startInIndex]=5
startInIndex=4
endInIndex=4
中序开始位置等于中序结束位置,而且前序开始位置之值等于中序开始位置之值,返回root=cglib.BinaryTreeNode@1db9742
根节点值:rootValue = 6
在中序遍历中找根结点的索引
还没找到,自增
rootInIndex=7
根节点值:rootValue = 8
前序的开始和结束位置相等
startPreIndex=7
endPreIndex=7
preOrder[startPreIndex]=8
inOrder[startInIndex]=8
startInIndex=6
endInIndex=6
中序开始位置等于中序结束位置,而且前序开始位置之值等于中序开始位置之值,返回root=cglib.BinaryTreeNode@106d69c
1 2 4 7 3 5 6 8test

相关文章
相关标签/搜索