首先要清楚二叉树的前中后遍历是什么样子的
- 前序遍历,先访问根节点,再访问左孩子节点,最后访问右孩子节点,就是中左右
- 中序遍历,左中右
- 后续遍历,左右中
可以看到其实这里的命名是根据遍历根节点的顺序来的,先遍历根节点就是先序遍历,中间遍历根节点就是中序遍历,最后遍历根节点就是后序遍历。
因为遍历方式的特点,可以知道,前序遍历的第一个结点肯定是根节点,后序遍历的最后一个结点肯定是根节点,中序遍历以根节点左边是左子树,右边是右子树。
通过二叉树的前序和中序遍历结果反推树就是利用上面的特征。
下面是代码
import java.util.Objects;
/**
* @description:
* @author: lkb
* @create: 2021/8/23
*/
public class MyTreeNode {
private Object value;
private MyTreeNode leftChild;
private MyTreeNode rightChild;
public MyTreeNode(Object value){
this.value = value;
}
public MyTreeNode(){
}
/**
* 构造树
* 前序遍历、中序遍历的结果构造树
* @return
*/
public void buildTree(Object[] preOrderArr, Object[] midOrderArr){
MyTreeNode root = buildTreeCore(new Arr(preOrderArr, 0, preOrderArr.length-1), new Arr(midOrderArr, 0, midOrderArr.length-1));
this.value = root.value;
this.leftChild = root.leftChild;
this.rightChild= root.rightChild;
}
private MyTreeNode buildTreeCore(Arr preOrderArr, Arr midOrderArr){
// find root index
MyTreeNode rootNode = new MyTreeNode(preOrderArr.getFirstValue());
if((preOrderArr.getStartIndex() == preOrderArr.getEndIndex())
&& (midOrderArr.getStartIndex() == midOrderArr.getEndIndex())){
return rootNode;
}
int rootIndex = midOrderArr.findMatchIndex(rootNode.value);
if(rootIndex < 0){
throw new RuntimeException("mid order arr wrong");
}
// recurse
int leftChildLength = rootIndex - midOrderArr.getStartIndex();
if(leftChildLength > 0){
Arr newPreArr = new Arr(preOrderArr.getArrValue(), preOrderArr.getStartIndex()+1, preOrderArr.getStartIndex() + leftChildLength);
Arr newMidArr = new Arr(midOrderArr.getArrValue(), midOrderArr.getStartIndex(), rootIndex-1);
rootNode.leftChild = buildTreeCore(newPreArr, newMidArr);
}
int rightChildLength = midOrderArr.getEndIndex() - rootIndex;
if(rightChildLength > 0){
Arr newPreArr = new Arr(preOrderArr.getArrValue(), preOrderArr.getStartIndex()+leftChildLength+1, preOrderArr.getEndIndex());
Arr newMidArr = new Arr(midOrderArr.getArrValue(), rootIndex + 1, midOrderArr.getEndIndex());
rootNode.rightChild = buildTreeCore(newPreArr, newMidArr);
}
return rootNode;
}
/**
* 先序遍历
* @return
*/
public static void pre(MyTreeNode rootNode){
if(null == rootNode){
return;
}
System.out.print(rootNode.value + "-");
pre(rootNode.leftChild);
pre(rootNode.rightChild);
}
/**
* 中序遍历
* @return
*/
public static void mid(MyTreeNode rootNode){
if(null == rootNode){
return;
}
mid(rootNode.leftChild);
System.out.print(rootNode.value + "-");
mid(rootNode.rightChild);
}
/**
* 中序遍历
* @return
*/
public static void post(MyTreeNode rootNode){
if(null == rootNode){
return;
}
post(rootNode.leftChild);
post(rootNode.rightChild);
System.out.print(rootNode.value + "-");
}
class Arr{
private Object[] arrValue;
private int startIndex;
private int endIndex;
public Object[] getArrValue() {
return arrValue;
}
public int getStartIndex() {
return startIndex;
}
public int getEndIndex() {
return endIndex;
}
public Arr(Object[] arrValue, int startIndex, int endIndex){
this.arrValue = arrValue;
this.startIndex = startIndex;
this.endIndex = endIndex;
}
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
for(int i = startIndex; i<=endIndex; i++){
stringBuilder.append(arrValue[i] );
}
return stringBuilder.toString();
}
public Object getFirstValue(){
return arrValue[startIndex];
}
public int findMatchIndex(Object value){
for(int i=startIndex; i<=endIndex; i++){
if(Objects.equals(arrValue[i], value)){
return i;
}
}
return -1;
}
}
}
下面是测试类
/**
* @description:
* @author: lkb
* @create: 2021/8/23
*/
public class Test {
public static void main(String[] args) {
Integer[] pre = new Integer[]{1,2,4,6,7,3,5};
Integer[] mid = new Integer[]{4,6,7,2,1,5,3};
MyTreeNode myTreeNode = new MyTreeNode();
myTreeNode.buildTree(pre, mid);
MyTreeNode.pre(myTreeNode);
System.out.println();
MyTreeNode.mid(myTreeNode);
System.out.println();
MyTreeNode.post(myTreeNode);
System.out.println();
}
}
结果如下