重建二叉树

在做题目的时候,做到通过前序遍历和中序遍历或则中序遍历和后序遍历的序列,来重新构建二叉树,并且返回根节点。如果做过剑指offer的题目的同学,应该做过这道题。
首先呢,我们先来熟悉一个前序遍历,中序遍历和后序遍历的顺序吧。
前序遍历:根节点,左孩子,右孩子
中序遍历:左孩子,根节点,有孩子
后序遍历:左孩子,有孩子,根节点
可以看出,可以根据根节点的所在位置来称呼遍历的顺序,这也是做这道题目的关键所在。
那么下面就开始实战吧。
已知一个二叉树的前序遍历序列是{1,2,4,7,3,5,6,8},中序遍历的序列是{4,7,2,1,5,3,8,6},要求重建二叉树,并且输出它的头节点。二叉树的节点定义如下:

//定义二叉树的节点
    public class TreeNode {
        int val;
        //定义树的节点,左节点和右节点
        TreeNode left;
        TreeNode right;
        TreeNode(int x){
            val = x;
        }
    }

首先理论分析一下吧。根据前序遍历和中序遍历的特点,可以知道前序遍历序列的第一个元素就是根节点,那么在中序遍历序列中,根节点的左边是左子树,右边是右子树。根据这个特性,就可以利用递归来分别构建左右子树。
代码如下:

//前序加中序遍历
    //前序遍历{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}
    //传入的参数:前序遍历的数组,前序遍历的起点索引,
    //前序遍历的终点的索引, 中序遍历的数组, 中序遍历的起点索引,
    //中序遍历的终点索引
    //索引就是在数组中的位置
    private TreeNode reConstructBinaryTree(int[] preorder,int startPreorder, int endPreorder,
                                            int [] inorder, int startInorder, int endInorder){
        //如果数组不存在,即二叉树不存在。返回空
        if(startPreorder > endPreorder || startInorder > endInorder)
            return null;

        //前序遍历的起点就是二叉树的根节点,可以说startPreorder就是0
        TreeNode root = new TreeNode(preorder[startPreorder]);

        //遍历中序遍历数组的所有元素,根据所给的例子就是从遍历从0到7
        for(int i=startInorder; i<= endInorder; i++){
            //如果中序遍历的数组元素中有等于等节点值的,即为根节点,根节点的索引为3
            if(inorder[i] == root.val){
                //构建左子树 在左子树中,前序遍历中,起点的索引是1,
                //值是2,终点索引是3,值是7;在中序遍历中,起点的索引是9,
                //值是4,终点的索引是2,值是2
                root.left=reConstructBinaryTree(preorder,startPreorder+1, startPreorder
                        +i - startInorder, inorder, startInorder, i-1);

                //由于中序遍历的特性,根节点左边的节点为左孩子部分,右边为右孩子部分
                //构建右子树,在右子树中,前序遍历中,起点的索引是4,
                //值是7,终点的索引是7,值是8; 在中序遍历中,
                //起点的索引是4,值是5,终点的索引是7,值是6,
                //然后调整相应的参数
                root.right=reConstructBinaryTree(preorder,i-startInorder+startPreorder+1,
                        endPreorder, inorder,i+1, endInorder);
                break;
            }
        }
        return root;
    }

public TreeNode reConstructBinaryTree(int [] preorder, int [] inorder) {
        TreeNode root = reConstructBinaryTree(preorder,0,preorder.length-1,inorder,
                0, inorder.length-1);
        return root;

    }

只要把定义函数和主函数加上,再输入相应的前序和终须遍历序列就能重新构造二叉树,并且输出头节点。
我的主函数是这样的,直接输出的是头节点的值,再这组数组中也就是1

public static void main(String[] args) {
        int[] preorder = new int[]{1, 2, 4, 7, 3, 5, 6, 8};
        int[] inorder = new int[]{4,7,2,1,5,3,8,6};

        Solution sn = new Solution();
        System.out.println(sn.reConstructBinaryTree(preorder,inorder).val);
    }

那么我们核对一下答案,根据剑指offer的题目的信息,可以得到完整的二叉树结构是这样的。
这里写图片描述
可以看到根节点的值是1.

那么下面我们再扩展一下,如果条件变成已知中序遍历和后序遍历序列,然后再做这道题目呢,其实差别并不大,对上面的代码稍作修改即可。主要的改变来自于,后序遍历序列的最后以为是头节点的数值,这与前序遍历序列第一位是头节点的数值,区别。

//中序遍历加后序遍历
    //中序遍历数组{4,7,2, 1, 5,3,8,6},后序遍历数组{7,4,2, 8,5,6,3, 1}
    //传入的参数:后序遍历的数组,前序遍历的起点索引,
    //前序遍历的终点的索引, 中序遍历的数组,
    // 中序遍历的起点索引,中序遍历的终点索引
    private TreeNode reConstructBinaryTree(int[] afterorder, int startafterorder, int endafterorder,
                 int [] inorder, int startInorder, int endInorder){
        //如果数组不存在,即二叉树不存在。返回空
        if(startafterorder > endafterorder || startInorder > endInorder)
            return null;

        //后序遍历的终点就是二叉树的根节点,可以说endafterorder就是7,值是1,修改一下
        TreeNode root = new  TreeNode(afterorder[endafterorder]);

        //遍历中序遍历数组的所有元素,根据所给的数组就是从遍历从0到7
        for(int i=startInorder; i<= endInorder; i++){
            //如果中序遍历的数组元素中有等于等节点值的,即为根节点,根节点的索引为3
            if(inorder[i] == root.val){
                //构建左子树 在左子树中,后序遍历中,起点的索引是0,
                //值是7,终点索引是2,值是2;在中序遍历中,
                //起点的索引是0,值是4,终点的索引是2,值是2(修改一下)
                root.left=reConstructBinaryTree(afterorder, startafterorder, i - startInorder+startafterorder-1,
                        inorder, startInorder,i-1);

                //由于中序遍历的特性,根节点左边的节点为左孩子部分,右边为右孩子部分
                //构建右子树,在右子树中,后序遍历中,起点的索引是3,
                //值是8,终点的索引是6,值是3; 在中序遍历中,起点的索引是4,
                //值是5,终点的索引是7,值是6(修改一下)
                root.right=reConstructBinaryTree(afterorder,i-startInorder+startafterorder,
                        endafterorder-1, inorder,i+1, endInorder);
                break;
            }
        }
        return root;
    }

有的人可能会问,为什么你不说前序遍历和后序遍历来重构二叉树呢?其实只有前序和后序遍历序列是不能一维确定二叉树的,所以这里就没有讨论了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值