还原本来的二叉树并不是一个非常简单的事,虽然思想比较简单,但过程却是比较繁琐。下面我拿先序序列和中序序列来讲一下原理吧。

从先序序列中我们一下子就可以得到二叉树的根节点是第一个元素,然后再中序序列中我们也可以找到这个元素(假设二叉树中所有的元素的值不相同)这样我们就可以把中序序列分成两部分,前部分和先序序列可求得左子树,后部分与先序序列可求得右子树。下面以左部分为例,在除去根节点的前序序列中的第二个元素,就是我们左子树的的第一个节点,然后继续在中序序列的前部分中找到相同的元素,再次对中序序列进行分割。····最后我们就可以得到恢复的二叉树了。

纯文字的讲述不太容易理解,下面我拿个具体的例子来分析吧。

比如

int[] preOrder = {7,10,4,3,1,2,8,11};  //前序序列
int[] inOrder = {4,10,3,1,7,11,8,2};  //中序序列

我们很容易在前序序列中得知7是根节点,接下来我们在中序序列中找到7所在的位置,那么此时4,10,3,1便是左子树对应的所有的节点。11,8,2是右子树所对应的所有的节点。

然后我们在前序序列中找到除根节点以外的第一个节点,那就是10,所以这就是左子树的第一个节点。然后我们在中序序列中找到10在第二个位置上,而10的左边有一个元素4,右边有3,1两个节点。这就说明4是节点10的左孩子节点,3,1为节点10的右子树上面的节点,然后再前序序列中我们便可以看出3是10的左孩子节点,而3的左边没有元素,说明3美誉哦左孩子节点,3的右边有一个元素1,说明3只有右孩子节点。至此,你是不是也掌握了恢复二叉树的方法了呢?

原理其实并不难理解,但是代码却不是特别好写。所以我拷贝了其他人做好的一份代码,大家一起欣赏一下吧。

package MyBinaryTree;

public class CreateBianryTreeByString {

        /**
         * Build Binary Tree from PreOrder and InOrder
         *  _______7______
           /              \
        __10__          ___2
       /      \        /
       4       3      _8
                \    /
                 1  11 

         */
        public static void main(String[] args) {
            CreateBianryTreeByString build=new CreateBianryTreeByString();
            int[] preOrder = {7,10,4,3,1,2,8,11};
            int[] inOrder = {4,10,3,1,7,11,8,2};  

            Node root=build.buildTreePreOrderInOrder(preOrder,0,preOrder.length-1,inOrder,0,preOrder.length-1);
            build.preOrder(root);
            System.out.println();
            build.inOrder(root);
        }  

        public Node buildTreePreOrderInOrder(int[] preOrder,int begin1,int end1,int[] inOrder,int begin2,int end2){
            if(begin1>end1||begin2>end2){
                return null;
            }
            int rootData=preOrder[begin1];
            Node head=new Node(rootData);
            int divider=findIndexInArray(inOrder,rootData,begin2,end2);
            int offSet=divider-begin2-1;
            Node left=buildTreePreOrderInOrder(preOrder,begin1+1,begin1+1+offSet,inOrder,begin2,begin2+offSet);
            Node right=buildTreePreOrderInOrder(preOrder,begin1+offSet+2,end1,inOrder,divider+1,end2);
            head.left=left;
            head.right=right;
            return head;
        }  

        public int findIndexInArray(int[] a,int x,int begin,int end){
            for(int i=begin;i<=end;i++){
                if(a[i]==x)return i;
            }
            return -1;
        }
        public void preOrder(Node n){
            if(n!=null){
                System.out.print(n.val+",");
                preOrder(n.left);
                preOrder(n.right);
            }
        }
        public void inOrder(Node n){
            if(n!=null){
                inOrder(n.left);
                System.out.print(n.val+",");
                inOrder(n.right);
            }
        }  

        class Node{
            Node left;
            Node right;
            int val;  

        public Node(int val){
            this.val=val;
        }
            public Node getLeft(){
                return left;
            }  

        public Node getRight(){
                return right;
            }  

        public int getVal(){
                return val;
            }  

        }
    }

测试结果:

7,10,4,3,1,2,8,11,//前序序列
4,10,3,1,7,11,8,2,//中序序列

Java由先序序列和中序序列还原二叉树的更多相关文章

  1. hdu1710-Binary Tree Traversals (由二叉树的先序序列和中序序列求后序序列)

    http://acm.hdu.edu.cn/showproblem.php?pid=1710 Binary Tree Traversals Time Limit: 1000/1000 MS (Java ...

  2. 48. leetcode 105题 由树的前序序列和中序序列构建树结构

    leetcode 105题,由树的前序序列和中序序列构建树结构.详细解答参考<剑指offer>page56. 先序遍历结果的第一个节点为根节点,在中序遍历结果中找到根节点的位置.然后就可以 ...

  3. 已知前序(后序)遍历序列和中序遍历序列构建二叉树(Leetcode相关题目)

    1.文字描述: 已知一颗二叉树的前序(后序)遍历序列和中序遍历序列,如何构建这棵二叉树? 以前序为例子: 前序遍历序列:ABCDEF 中序遍历序列:CBDAEF 前序遍历先访问根节点,因此前序遍历序列 ...

  4. L2-006 树的遍历 (25 分) (根据后序遍历与中序遍历建二叉树)

    题目链接:https://pintia.cn/problem-sets/994805046380707840/problems/994805069361299456 L2-006 树的遍历 (25 分 ...

  5. 玩透二叉树(Binary-Tree)及前序(先序)、中序、后序【递归和非递归】遍历

    基础预热: 结点的度(Degree):结点的子树个数:树的度:树的所有结点中最大的度数:叶结点(Leaf):度为0的结点:父结点(Parent):有子树的结点是其子树的根节点的父结点:子结点/孩子结点 ...

  6. python数据结构之树和二叉树(先序遍历、中序遍历和后序遍历)

    python数据结构之树和二叉树(先序遍历.中序遍历和后序遍历) 树 树是\(n\)(\(n\ge 0\))个结点的有限集.在任意一棵非空树中,有且只有一个根结点. 二叉树是有限个元素的集合,该集合或 ...

  7. c/c++ 用前序和中序,或者中序和后序,创建二叉树

    c/c++ 用前序和中序,或者中序和后序,创建二叉树 用前序和中序创建二叉树 //用没有结束标记的char*, clr为前序,lcr为中序来创建树 //前序的第一个字符一定是root节点,然后去中序字 ...

  8. 03-树3. Tree Traversals Again (25)将先序遍历和中序遍历转为后序遍历

    03-树3. Tree Traversals Again (25) 题目来源:http://www.patest.cn/contests/mooc-ds/03-%E6%A0%913 An inorde ...

  9. 小小c#算法题 - 11 - 二叉树的构造及先序遍历、中序遍历、后序遍历

    在上一篇文章 小小c#算法题 - 10 - 求树的深度中,用到了树的数据结构,树型结构是一类重要的非线性数据结构,树是以分支关系定义的层次结构,是n(n>=0)个结点的有限集.但在那篇文章中,只 ...

随机推荐

  1. 读书笔记-《Maven实战》-关于Maven依赖传递的思考 2018/4/26

    上次读书笔记中,提到了依赖传递.看着依赖传递表,一直在思考为什么会是这样. 先看传递表: compile test provided runtime compile test provided run ...

  2. ftp传二进制文件时一定要用二进制模式,否则内容会有变化,造成后处理莫名其妙的错误,还以为传输前后内容一致,其实已变化。

    ftp传二进制文件时一定要用二进制模式,否则内容会有变化,造成后处理莫名其妙的错误,还以为传输前后内容一致,其实已变化.

  3. delphi 线程教学第六节:TList与泛型

    第六节: TList 与泛型   TList 是一个重要的容器,用途广泛,配合泛型,更是如虎添翼. 我们先来改进一下带泛型的 TList 基类,以便以后使用. 本例源码下载(delphi XE8版本) ...

  4. git使用之错误分析及解决(持续更新)

    错误一: 使用 $ git push -u origin master 出现如下错误: error: src refspec master does not match any. error: fai ...

  5. MySQL where 子句

    MySQL where 子句 我们知道从MySQL表中使用SQL SELECT 语句来读取数据. 如需有条件地从表中选取数据,可将 WHERE 子句添加到 SELECT 语句中. 语法 以下是SQL ...

  6. 决策树之ID3、C4.5

    决策树是一种类似于流程图的树结构,其中,每个内部节点(非树叶节点)表示一个属性上的测试,每个分枝代表该测试的一个输出,而每个树叶节点(或终端节点存放一个类标号).树的最顶层节点是根节点.下图是一个典型 ...

  7. Java内存泄漏分析系列之五:常见的Thread Dump日志案例分析

    原文地址:http://www.javatang.com 症状及解决方案 下面列出几种常见的症状即对应的解决方案: CPU占用率很高,响应很慢 按照<Java内存泄漏分析系列之一:使用jstac ...

  8. JAVA中的常量定义在class中还是interface中比较合理?

    本文地址:http://blog.csdn.net/sushengmiyan 本文作者:苏生米沿 java中使用的常量可以集中定义在一个文件中. 有两种解决方案: 1.在Constants.java中 ...

  9. C实战:强大的程序调试工具GDB

    C实战:强大的程序调试工具GDB 1.基本调试 这里只列举最最常用的GDB命令. 1.1 启动GDB gdb program:准备调试程序.也可以直接进入gdb,再通过file命令加载. 1.2 添加 ...

  10. 电脑hash破解

    我一直在想,到底用什么样的方式才能较长时间地控制已经得到了权限的目标呢?留后门,种木马,甚至是Rootkit?留的Webshell痕迹太明显,哪怕是一句话的Webshell,都极容易被管理员清除.放了 ...