重建二叉树

问题

  输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树。

思路

  首先找到先序遍历的第一个节点,就是根节点,然后在中序遍历中找到根节点。此时,根节点左右两边,分别是左右子树的中序遍历。再对于先序遍历,从第二个节点开始,到中序遍历中左子树的长度,就是左子树的先序遍历。同理,右子树也是一样,这是一个递归过程。

    public BinaryTreeNode getTheRoot(List<Integer> preorder,
            List<Integer> inorder, int count) {

        //前序排列中的第一个数字为当前根节点的值
        int rootValue = preorder.get(0);
        BinaryTreeNode root = new BinaryTreeNode();
        root.value = rootValue;

        //如果count=1,则表示当前节点为叶子节点,直接返回
        if (count == 1) {

            return root;
        }

        // 根节点的值在中序排列中的位置
        int index = 0;
        for (int i : inorder) {

            if (i == rootValue) {

                break;
            }
            index++;
        }

        //表示在中序排列中没有找到根节点的值,则表示前序排列或者中序排列的输入有误
        if (index == count) {

            throw new RuntimeException("错误的排序输入!");
        }

        //如果index > 0,则表示当前有左子树
        if (index > 0) {

            // 左子树的前序排列从当前前序排列的第二个值(去掉当前根节点)开始,包含左子树个数个值(index)
            List<Integer> startPreorder = preorder.subList(1, (index + 1));
            // 左子树的中排列从当前中序排列的第一个值开始,直到根节点的位置(不包含根节点)
            List<Integer> startInorder = inorder.subList(0, index);
            
            root.left = getTheRoot(startPreorder, startInorder, index);
        }

        //如果index > 0,则表示当前有有子树
        if (index < count - 1) {
            
            List<Integer> endPreorder = preorder.subList((index + 1), count);
            List<Integer> endInorder = inorder.subList((index + 1), count);
            
            //这里为什么是count - index - 1 大家可以画图思考一下
            root.right = getTheRoot(endPreorder, endInorder, (count - index - 1));
        }
        
        return root;
    }

总结

  首先要熟悉二叉树的前序遍历,中序遍历,以及后序遍历,再加上递归的思想,就可以实现。

原文地址:https://www.cnblogs.com/a294098789/p/5400557.html