构建二叉树

二叉树的前序遍历123456 ,中序遍历321546 ,构建二叉树

从前序遍历知道根节点,从中序遍历划分左右子树,然后从前序遍历知道子树的根节点,从中序遍历知道子树的左右子树,以此类推,直到全部构建完。

/**
     * 二叉树节点类
     */
    public static class BinaryTreeNode {
        int value;
        BinaryTreeNode left;
        BinaryTreeNode right;
    }
/**
     * 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二节树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
     * @param preorder 前序遍历
     * @param inorder  中序遍历
     * @return 树的根结点
     */
    public static BinaryTreeNode construct(int[] preorder, int[] inorder){
        // 输入的合法性判断,两个数组都不能为空,并且都有数据,而且数据的数目相同
        if (preorder == null || inorder == null
                || preorder.length != inorder.length
                || inorder.length < 1) return null;

        return construct(preorder,0,preorder.length-1,inorder,0,inorder.length-1);
    }

    /**
     * 这里不改变序列,而是改变开始位置与结束位置,可以理解为调整游标,从而达到改变序列的要求
     * 实际就是改便了序列的有效位,根据序列的有效位,找出树的左子树与右子树有效位,递归构建树
     * @param preorder 前序遍历序列
     * @param ps        前序遍历序列的开始位置
     * @param pe        前序遍历序列的结束位置
     * @param inorder  中序遍历序列
     * @param is        中序遍历序列的开始位置
     * @param ie        中序遍历序列的结束位置
     * @return          树的根结点
     */
    public static BinaryTreeNode construct(int[] preorder, int ps, int pe, int[] inorder, int is, int ie){

        // 开始大于位置结束位置,说明已经没有需要处理的元素了
        if (ps > pe || is > ie){
            return null;
        }
        // 取前序遍历的第一个数字,就是当前的根结点
        int curRoot = preorder[ps];
        int index = is;
        // 在中序遍历的数组中找根结点的位置
        while (index <= ie && inorder[index] != curRoot)
            index++;

        // 如果在整个中序遍历的数组中没有找到,说明输入的参数是不合法的,抛出异常
        if (index > ie)
            throw new RuntimeException("非法输入");

        BinaryTreeNode node = new BinaryTreeNode();
        node.value = curRoot;

        // 构建当前根结点的左子树,左子树的元素个数:ps+1+index-is-1 - (ps+1) + 1 = index-is
        // 左子树对应的前序遍历位置[ps+1,ps+1+index-is-1]
        // 右子树对应的中序遍历位置[is,index-1]
        node.left = construct(preorder,ps+1,ps+index-is,inorder,is,index-1);

        // 构建当前根结点的右子树,右子树的元素个数ie-index
        // 右子树对应的前序遍历的位置[ps+index-is+1,pe]
        // 右子树对应的中序遍历的位置[index+1,ie]
        node.right = construct(preorder,ps+1+index-is,pe,inorder,index+1,ie);

        // 返回当前的根节点
        return node;

    }

二叉树的前序遍历,中序遍历,后序遍历,递归实现。

private static void preOrderTraverse(BinaryTreeNode treeNode){
        if (treeNode == null)
            return;
        System.out.print(treeNode.value);
        preOrderTraverse(treeNode.left);
        preOrderTraverse(treeNode.right);
    }

    private static void inOrderTraverse(BinaryTreeNode treeNode){
        if (treeNode == null)
            return;
        inOrderTraverse(treeNode.left);
        System.out.print(treeNode.value);
        inOrderTraverse(treeNode.right);
    }

    private static void postOrderTraverse(BinaryTreeNode treeNode){
        if (treeNode == null)
            return;
        postOrderTraverse(treeNode.left);
        postOrderTraverse(treeNode.right);
        System.out.print(treeNode.value);
    }

二叉树遍历的性质

已知前序遍历和中序遍历序列,可以唯一确定一棵二叉树。

已知后序遍历和中序遍历序列,可以唯一确定一棵二叉树。

需要注意的是,已知前序和后序遍历,是不能确定一棵二叉树的

因为比如前序序列是ABC ,后序序列是CBA ,我们可以确定A 一定是根节点,但接下来哪个是左子树,哪个右子树,就不能唯一的确定了。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值