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

原文地址:https://www.cnblogs.com/FanJava/p/9492222.html