Java已知前序和中序/中序和后序还原二叉树
数据结构的题目:
只知道前序和中序怎么知道二叉树呢??
只知道中序和后序怎么知道二叉树呢??
现在我们来了解一下基础的原理:
先知道概念噢!qwq~~~
前序遍历:先访问当前节点,再访问当前节点的左子树,最后访问当前节点的右子树。对于二叉树,深度遍历与此同。规律:根在前;子树在根后且左子树比右子树靠前,且第一个就是根节点;
中序遍历:先访问当前节点的左子树,然后访问当前节点,最后是当前节点的右子树,二叉树,中序遍历会得到数据升序效果。规律:根在中;左子树在跟左边,右子树在根右边,左边部分是根结点的左子树的中序遍历序列,右边部分是根结点的右子树的中序遍历序列 ;
后序遍历:先访问当前节点的左子树,然后是当前节点的又子树,最后是当前节点。规律:根在后;子树在根前且左子树比右子树靠前,且最后一个节点是根节点。
一、前序+中序
- 根据前序序列的第一个元素建立根结点;
- 在中序序列中找到该元素,确定根结点的左右子树的中序序列;
- 在前序序列中确定左右子树的前序序列;
- 由左子树的前序序列和中序序列建立左子树;
- 由右子树的前序序列和中序序列建立右子树。
如:已知一棵二叉树的先序遍历序列和中序遍历序列分别是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
二、后序+中序:
已知一棵二叉树的后序序列和中序序列,构造该二叉树的过程如下:
- 根据后序序列的最后一个元素建立根结点;
- 在中序序列中找到该元素,确定根结点的左右子树的中序序列;
- 在后序序列中确定左右子树的后序序列;
- 由左子树的后序序列和中序序列建立左子树;
- 由右子树的后序序列和中序序列建立右子树
如还是上面题目:如:已知一棵二叉树的后序遍历序列和中序遍历序列分别是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 的右子树类似可以推出。然后还原。
三、前序+后序
前序和后序在本质上都是将父节点与子结点进行分离,但并没有指明左子树和右子树的能力,因此得到这两个序列只能明确父子关系,而不能确定一个二叉树。 故此法无。不能唯一确定一个二叉树。
相信到这里大家都理解了叭~
那我就直接上代码了噢:
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
宝宝们喜欢请点个关注噢爱你们~~
上一篇: ADB入门
推荐阅读
-
Python利用前序和中序遍历结果重建二叉树的方法
-
Python实现输入二叉树的先序和中序遍历,再输出后序遍历操作示例
-
PHP实现二叉树深度优先遍历(前序、中序、后序)和广度优先遍历(层次)实例详解
-
[PHP] 算法-根据前序和中序遍历结果重建二叉树的PHP实现
-
c/c++ 用前序和中序,或者中序和后序,创建二叉树
-
Python实现二叉树前序、中序、后序及层次遍历示例代码
-
【算法】二叉树的前序、中序、后序、层序遍历和还原。
-
Python二叉树的遍历操作示例【前序遍历,中序遍历,后序遍历,层序遍历】
-
已知后序遍历和中序遍历求层序遍历(树的遍历)
-
C++实现LeetCode(105.由先序和中序遍历建立二叉树)