欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java已知前序和中序/中序和后序还原二叉树

程序员文章站 2022-03-27 10:25:39
...

数据结构的题目:

只知道前序和中序怎么知道二叉树呢??
只知道中序和后序怎么知道二叉树呢??

现在我们来了解一下基础的原理:

先知道概念噢!qwq~~~

前序遍历:先访问当前节点,再访问当前节点的左子树,最后访问当前节点的右子树。对于二叉树,深度遍历与此同。规律:根在前;子树在根后且左子树比右子树靠前,且第一个就是根节点;

中序遍历:先访问当前节点的左子树,然后访问当前节点,最后是当前节点的右子树,二叉树,中序遍历会得到数据升序效果。规律:根在中;左子树在跟左边,右子树在根右边,左边部分是根结点的左子树的中序遍历序列,右边部分是根结点的右子树的中序遍历序列 ;

后序遍历:先访问当前节点的左子树,然后是当前节点的又子树,最后是当前节点。规律:根在后;子树在根前且左子树比右子树靠前,且最后一个节点是根节点。

一、前序+中序

  1. 根据前序序列的第一个元素建立根结点;
  2. 在中序序列中找到该元素,确定根结点的左右子树的中序序列;
  3. 在前序序列中确定左右子树的前序序列;
  4. 由左子树的前序序列和中序序列建立左子树;
  5. 由右子树的前序序列和中序序列建立右子树。
    如:已知一棵二叉树的先序遍历序列和中序遍历序列分别是abdgcefh、dgbaechf,求二叉树及后序遍历序列。
    先序:abdgcefh—>a bdg cefh

中序:dgbaechf---->dgb a echf

得出结论:a是树根,a有左子树和右子树,左子树有bdg结点,右子树有cefh结点。
先序:bdg—>b dg

中序:dgb —>dg b

得出结论:b是左子树的根结点,b无右子树,有左子树。
先序:dg---->d g

中序:dg----->dg

得出结论:d是b左子树的根节点,d无左子树,g是d的右子树

然后对于a 的右子树类似可以推出

最后还原:

                                                          a
                                  b                                                 c

           d                                                       e                                f

                 g                                                                      h

后序遍历:gdbehfca

二、后序+中序:

已知一棵二叉树的后序序列和中序序列,构造该二叉树的过程如下:

  1. 根据后序序列的最后一个元素建立根结点;
  2. 在中序序列中找到该元素,确定根结点的左右子树的中序序列;
  3. 在后序序列中确定左右子树的后序序列;
  4. 由左子树的后序序列和中序序列建立左子树;
  5. 由右子树的后序序列和中序序列建立右子树

如还是上面题目:如:已知一棵二叉树的后序遍历序列和中序遍历序列分别是gdbehfca、dgbaechf,求二叉树

后序:gdbehfca---->gdb ehfc a

中序:dgbaechf----->dgb a echf
得出结论:a是树根,a有左子树和右子树,左子树有bdg结点,右子树有cefh结点。
后序:gdb---->gd b

中序:dgb----->dg b

得出结论:b是a左子树的根节点,无右子树,有左子树dg。

后序:gd---->g d

中序:dg----->d g

得出结论:d是b的左子树根节点,g是d的右子树。

然后对于a 的右子树类似可以推出。然后还原。
Java已知前序和中序/中序和后序还原二叉树

三、前序+后序

前序和后序在本质上都是将父节点与子结点进行分离,但并没有指明左子树和右子树的能力,因此得到这两个序列只能明确父子关系,而不能确定一个二叉树。 故此法无。不能唯一确定一个二叉树。


相信到这里大家都理解了叭~
那我就直接上代码了噢

import java.util.*;

import tree.BinaryTreeDemo.BinaryTree;

 
/**
 * 根据前序和中序还原二叉树
 *
 */

 class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}
 
 
 /*
public class tee2 {
    public static TreeNode1 reConstructBinaryTree(int [] pre,int [] in) {
        //1.由前序遍历确认根节点
        int node=pre[0];
        TreeNode1 tree=new TreeNode1(node);

        //2.由中序遍历确认左右子树节点
        ArrayList<Integer> leftTreeForIn=new ArrayList<>();
        ArrayList<Integer> rightTreeForIn=new ArrayList<>();
        int nodePosition=-1;
        for(int i=0;i<in.length;i++){
            if(in[i]==node){
                nodePosition=i;  //确认根节点在中序遍历中的位置
            }
            //根据根节点将左右子树的节点分别放入两个list中
            if(nodePosition<0){
                leftTreeForIn.add(in[i]); 
            }else if(nodePosition>=0 && nodePosition<i){
                rightTreeForIn.add(in[i]);
            }
        }

        //3.为树添加左右子树
        if(leftTreeForIn.size()>0){ 
            TreeNode1 left;
            if(leftTreeForIn.size()==1){  //判断左子树是否有叶子节点,左子树只有1个节点则表示无叶子节点
                left=new TreeNode1(leftTreeForIn.get(0));
            }else{ //有叶子节点则进行递归操作
                int[] leftTreeForPre=new int[leftTreeForIn.size()];
                for(int i=0;i<leftTreeForIn.size();i++){
                    leftTreeForPre[i]=pre[i+1];
                }
                left=reConstructBinaryTree(leftTreeForPre,Arrays.stream(leftTreeForIn.toArray(new Integer[]{})).mapToInt(Integer::valueOf).toArray());
            }
            tree.left=left;
        }

        if(rightTreeForIn.size()>0){
            TreeNode1 right;
            if(rightTreeForIn.size()==1){
                right=new TreeNode1(rightTreeForIn.get(0));
            }else{
                int[] rightTreeForPre=new int[rightTreeForIn.size()];
                for(int i=0;i<rightTreeForIn.size();i++){
                    rightTreeForPre[i]=pre[i+1+leftTreeForIn.size()];
                }
                right=reConstructBinaryTree(rightTreeForPre,Arrays.stream(rightTreeForIn.toArray(new Integer[]{})).mapToInt(Integer::valueOf).toArray());
            }
            tree.right=right;
        }
       return tree;

    }

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

        TreeNode1 tree=reConstructBinaryTree(pre,in);
        System.out.println(tree.left.left.right.val);
    }
}
*/


/**
*根据中序和后序还原二叉树
*
*
*
*    3
   / \
  9  20
    /  \
   15   7

*/

	 
public class tee2 {
    public static void prevPrintTreeNode(TreeNode root){
    if(root == null){
    return;
}
System.out.print(root.val+" ");
//运用了递归
prevPrintTreeNode(root.left);
prevPrintTreeNode(root.right);
}

public static void inPrintTreeNode(TreeNode root){
if(root == null){
    return;
}
//运用了递归
inPrintTreeNode(root.left);
System.out.print(root.val+" ");
inPrintTreeNode(root.right);
}
    

    public  static TreeNode reConstructBinaryTree(int [] prev,int [] in) {
    //不管什么遍历方式,结果长度肯定是一样的,都是总结点数
        if(prev.length!= in.length || prev.length<1){
            return null;
        }
    //只有一个节点,那就是根节点
        if(prev.length == 1){
            return new TreeNode(prev[0]);
        }
    //在中序遍历结果中找根节点
        int index = -1;
        for(int i=0;i<in.length;i++){
            if(in[i]==prev[0]){
                index=i;
                break;
            }
        }
    //没找到,说明数据有问题
        if(index==-1){
            return null;
        }
    //找到根节点了
        TreeNode root = new TreeNode(prev[0]);
    //得到左子树的前序遍历结果
        int[] lChildPrev = new int[index];
        System.arraycopy(prev,1,lChildPrev,0,index);
    //得到左子树的中序遍历结果
        int[] lChildin = new int[index];
        System.arraycopy(in,0,lChildin,0,index);
    //通过递归,得到左子树结构
        root.left=reConstructBinaryTree(lChildPrev,lChildin);
        
    //得到右子树的前序遍历结果
        int[] rChildPrev = new int[in.length-1-index];
        System.arraycopy(prev,index+1,rChildPrev,0,in.length-1-index);
    //得到右子树的中序遍历结果
        int[] rChildin = new int[in.length-1-index];
        System.arraycopy(in,index+1,rChildin,0,in.length-1-index);
    //通过递归,得到右子树结构
        root.right=reConstructBinaryTree(rChildPrev,rChildin);
    //得到完整的二叉树结构
        return root;
    }

    public static void main(String[] args){
    int[] prev = {1,2,4,7,3,5,6,8};
    int[] in = {4,7,2,1,5,3,8,6};
    TreeNode root = reConstructBinaryTree(prev,in);
    prevPrintTreeNode(root);
    System.out.println();
    inPrintTreeNode(root);
    }
}

运行结果:
1 2 4 7 3 5 6 8
4 7 2 1 5 3 8 6

宝宝们喜欢请点个关注噢爱你们~~