zoukankan      html  css  js  c++  java
  • java基础编程——重建二叉树

    题目描述

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

    题目代码

    /**
     * Created by YuKai Fan on 2018/8/17.
     */
    public class ReBuildTreeNode {
        public static void main(String[] args) {
            ReBuildTreeNode rtn = new ReBuildTreeNode();
            int[] pre = {1,2,4,7,3,5,6,8};
            int[] in = {4,7,2,1,5,3,8,6};
            TreeNode treeNode = rtn.reConstructBinaryTree(pre, in);
            TreeNode treeNode1 = rtn.reConstructBinaryTree2(pre, 0, pre.length, in, 0, in.length);
            System.out.println(treeNode.left.val);
        }
    
        /*
        分析:
            前序遍历:root->left->right
            中序遍历:left->root->right
            所以根据前序遍历可以得到pre[0]就是二叉树的root根节点,在根据中序遍历集合可以得到,该根节点的左边是左子树,右边是右子树
            调用递归,可以将得到的前序和中序左子树集合看成一个新的二叉树,与上方同理,调用递归,而右子树也是同理可得。
        方法一:
            这个方法使用了数组Arrays的API:copyOfRange(array,i,j)方法,可以从i开始到j(不包括j)复制一个array数组,并产生一个新的数组,
            用这种方法可以得到该二叉树的左子树和右子树,在调用递归
         */
        public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
            if (pre.length == 0 || in.length == 0) {
                return null;
            }
            TreeNode tn = new TreeNode(pre[0]);
            for (int i = 0; i < in.length; i++) {
                if (in[i] == pre[0]) {
                    tn.left = reConstructBinaryTree(Arrays.copyOfRange(pre,1,i+1),Arrays.copyOfRange(in,0,i));
                    tn.right = reConstructBinaryTree(Arrays.copyOfRange(pre,i+1,pre.length),Arrays.copyOfRange(in,i+1,in.length));
                }
            }
            return tn;
        }
        /*
        方法二
         */
        public TreeNode reConstructBinaryTree2(int [] pre,int sPre, int ePre,int [] in, int sIn, int eIn) {
            if (sPre > ePre || sIn > eIn) {
                return null;
            }
            TreeNode tn = new TreeNode(pre[sPre]);
            for (int i = sIn; i < eIn; i++) {
                if (in[i] == pre[sPre]) {
                    tn.left = reConstructBinaryTree2(pre,sPre+1, sPre+i-sIn,in,sIn,i-1);
                    tn.right = reConstructBinaryTree2(pre,sPre+i-sIn+1,ePre,in,i+1,eIn);
                }
            }
            return tn;
        }
    }
    /**
     * Created by YuKai Fan on 2018/8/17.
     */
    public class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode(int val) {
            this.val = val;
        }
    }

    题目延伸

    二叉树是一种非常重要的数据结构,非常多其他数据结构都是基于二叉树的基础演变而来的。对于二叉树,有深度遍历和广度遍历,深度遍历有前序、中序以及后序三种遍历方法,广度遍历即我们寻常所说的层次遍历。由于树的定义本身就是递归定义,因此採用递归的方法去实现树的三种遍历不仅easy理解并且代码非常简洁,而对于广度遍历来说,须要其他数据结构的支撑。比方堆了。所以。对于一段代码来说,可读性有时候要比代码本身的效率要重要的多。

    四种基本的遍历思想为:

    前序遍历:根结点 ---> 左子树 ---> 右子树

    中序遍历:左子树---> 根结点 ---> 右子树

    后序遍历:左子树 ---> 右子树 ---> 根结点

    层次遍历:仅仅需按层次遍历就可以

    一、前序遍历

    依据上文提到的遍历思路:根结点 ---> 左子树 ---> 右子树,递归方法
        public void preOrderTraverse1(TreeNode root) {  
                if (root != null) {  
                    System.out.print(root.val+"  ");  
                    preOrderTraverse1(root.left);  
                    preOrderTraverse1(root.right);  
                }  
            }  

    二、中序遍历

    依据上文提到的遍历思路:左子树 ---> 根结点 ---> 右子树,递归方法

        public void inOrderTraverse1(TreeNode root) {  
                if (root != null) {  
                    inOrderTraverse1(root.left);  
                    System.out.print(root.val+"  ");  
                    inOrderTraverse1(root.right);  
                }  
            }  

    三、后序遍历

    依据上文提到的遍历思路:左子树 ---> 右子树 ---> 根结点

        public void postOrderTraverse1(TreeNode root) {  
                if (root != null) {  
                    postOrderTraverse1(root.left);  
                    postOrderTraverse1(root.right);  
                    System.out.print(root.val+"  ");  
                }  
            }  

    四、层次遍历

    层次遍历的代码比較简单。仅仅须要一个队列就可以。先在队列中增加根结点。之后对于随意一个结点来说。在其出队列的时候,訪问之。同一时候假设左孩子和右孩子有不为空的。入队列。代码例如以下:

     

        public void levelTraverse(TreeNode root) {  
                if (root == null) {  
                    return;  
                }  
                LinkedList<TreeNode> queue = new LinkedList<>();  
                queue.offer(root);  
                while (!queue.isEmpty()) {  
                    TreeNode node = queue.poll();  
                    System.out.print(node.val+"  ");  
                    if (node.left != null) {  
                        queue.offer(node.left);  
                    }  
                    if (node.right != null) {  
                        queue.offer(node.right);  
                    }  
                }  
            }  

     

    五、深度优先遍历 事实上深度遍历就是上面的前序、中序和后序。可是为了保证与广度优先遍历相照顾,也写在这。代码也比較好理解,事实上就是前序遍历,代码例如以下:

        public void depthOrderTraverse(TreeNode root) {  
                if (root == null) {  
                    return;  
                }  
                LinkedList<TreeNode> stack = new LinkedList<>();  
                stack.push(root);  
                while (!stack.isEmpty()) {  
                    TreeNode node = stack.pop();  
                    System.out.print(node.val+"  ");  
                    if (node.right != null) {  
                        stack.push(node.right);  
                    }  
                    if (node.left != null) {  
                        stack.push(node.left);  
                    }  
                }  
            }  

    借鉴的博客:https://www.cnblogs.com/llguanli/p/7363657.html

  • 相关阅读:
    dapper 可空bool转换出错及解决方案
    python监控linux内存并写入mongodb
    MongoDB 线上环境按照及配置(授权方式启动)
    工作吐槽
    visual studio 调试grunt
    require js 将config和入口函数分开写
    【转】Contrary to the answers here, you DON'T need to worry about encoding!
    [ 转]国内有时抽风,无法更新adt的解决方案
    The ToolStripMenuItem visible value always false
    ArcGis : unable to save as template this document is already based on another template
  • 原文地址:https://www.cnblogs.com/FanJava/p/9492222.html
Copyright © 2011-2022 走看看