根据先序序列和中序序列生成二叉树(Java)

实现思路

在二叉树中,有三种主要的遍历方式(假设父节点为N,左孩子为L,右孩子为R):

先序遍历:N -> L -> R

中序遍历:L -> N -> R

后序遍历:L -> R -> N

根据先序序列和中序序列生成二叉树(Java)_第1张图片
假设现有一颗二叉树如上图所示,上述二叉树的先序遍历和中序遍历结果为:

先序遍历:ABCDEF

中序遍历:CBDAEF

分析: 先序遍历服从规则“根左右”,所以,对于一个先序遍历得到的数组,第一个元素一定是根节点;中序遍历服从规则”左根右“,所以由此可知,对于一个中序遍历得到的数组,根节点左边的元素都属于根节点的左子树,而根节点右边的元素都属于根节点的右子树。所以,可以先通过先序遍历的第一个元素确定根节点,然后通过中序遍历结合根节点,获得当前根节点的左右子树,再将子树看成一棵独立的树,继续使用先序遍历判断根节点,中序遍历判断子树的方式,最终建立起整棵树 。

详细算法如下:

1、先序或中序为空则返回,否则,通过先序序列创建根结点,再通过根节点在中序遍历的位置找出左右子树。

2、在根绝点的左子树中,找左子树的根结点(在先序中找),转步骤1。

3、在根节点的右子树中,找右子树的根结点(在先序中找),转步骤1。

根据上述算法,可以看出创建出二叉树的关键在于先序序列和中序序列的划分,在对序列进行划分的时候要注意边界的问题。

代码实现

递归方式

    import java.util.Arrays;
    public class Solution {
     //创建二叉树
    public static Node buildTree(char[] preOrders, char[] inOrders) {
        if (preOrders.length == 0 || inOrders.length == 0) {
            return null;
        }

        Node node = new Node(preOrders[0]);
        int index = search(0, inOrders.length, inOrders, node.getData());

        //构建左子树
        node.setLChild(buildTree(Arrays.copyOfRange(preOrders, 1, index + 1),
                Arrays.copyOfRange(inOrders, 0, index)));

        //构建右子树
        node.setRChild(buildTree(Arrays.copyOfRange(preOrders, index + 1, preOrders.length),
                Arrays.copyOfRange(inOrders, index + 1, inOrders.length)));

        return node;
    }


    //得到索引
    private static int search(int start,int end,char[] inOrders,char data){
        for (int i = start; i < end; i++) {
            if (data == inOrders[i]) {
                return i;
            }
        }
        return -1;
    }
}

非递归方式

public class Solution {
    public TreeNode buildTree(int [] pre,int [] in) {
        TreeNode root=buildTree(pre,0,pre.length-1,in,0,in.length-1);
        return root;
    }
     //先序序列{1,2,4,7,3,5,6,8}和中序序列序列{4,7,2,1,5,3,8,6}
    private TreeNode buildTree(int [] pre,int startPre,int endPre,int [] in,int       startIn,int endIn) {
        if(startPre>endPre||startIn>endIn)
            return null;
        TreeNode root=new TreeNode(pre[startPre]);
        for(int i=startIn;i<=endIn;i++)
            if(in[i]==pre[startPre]){
                root.left=buildTree(pre,startPre+1,startPre+i-startIn,in,startIn,i-1);
                root.right=buildTree(pre,i-startIn+startPre+1,endPre,in,i+1,endIn);
                      break;
            }
                 
        return root;
    }
}

你可能感兴趣的:(数据结构与算法)