算法-从二叉树的前序和中序遍历结果生成树(递归实现)

392 阅读2分钟

首先要清楚二叉树的前中后遍历是什么样子的

  • 前序遍历,先访问根节点,再访问左孩子节点,最后访问右孩子节点,就是中左右
  • 中序遍历,左中右
  • 后续遍历,左右中

可以看到其实这里的命名是根据遍历根节点的顺序来的,先遍历根节点就是先序遍历,中间遍历根节点就是中序遍历,最后遍历根节点就是后序遍历。

因为遍历方式的特点,可以知道,前序遍历的第一个结点肯定是根节点,后序遍历的最后一个结点肯定是根节点,中序遍历以根节点左边是左子树,右边是右子树。

通过二叉树的前序和中序遍历结果反推树就是利用上面的特征。

下面是代码

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();
    }
}

结果如下

image.png