二叉树的创建以及前序、中序、后序、层次遍历

本文详细介绍了如何根据前序、中序、后序序列创建二叉树,并讲解了二叉树的前序、中序、后序、层次遍历的递归与非递归实现,以及二叉树的Z字形遍历方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二叉树的创建

前序序列和中序序列创建二叉树

        我们都知道,二叉树的前序遍历规则和中序遍历规则。

        前序遍历规则为:访问根节点->前序遍历左子树->前序遍历右子树。

        中序遍历规则为:中序遍历左子树->访问根节点->中序遍历右子树。

        我们以下面的二叉树为例,看看,这两种遍历规则有什么联系:

        如图,是一颗二叉树,我们先写出 它的 前序序列和中序序列。

在这里插入图片描述
        根据二叉树的前序遍历规则,我们可以写出其前序序列为:{3,9,8,5,10,20,15,7}

        根据二叉树的中序遍历规则,我们可以写出其中序序列为: {8,9,10,5,20,3,15,7}

        此时,我们可以发现,前序序列中的每一个节点对应在中序序列中的所在的位置,其之前都是该节点的左子树包含的所有节点,其之后都是该节点的右子树包含的所有节点。

        举个例子:前序序列中 3 这个节点,其在中序序列中的下标为5,在下标5之前的 8、9、10、5、20这些节点,都是3这个节点的左子树所包含的全部节点,在下标5之后的15、7这些节点,都是3这个节点的右子树所包含的全部节点。

        所以,我们在创建二叉树的时候,就可以利用这个特征来创建。即前序序列中的节点都可以当做一棵二叉树的根节点,根据这个节点在中序序列中的位置,来确定这棵二叉树的左右子树。找到该二叉树的左右子树后,又分别以左右子树的基准,查找左右子树的左右子树的根节点。

在这里插入图片描述
        根据上述思路,我们先通过前序序列找到整个二叉树的根节点:3。

        紧接着,查找3在中序序列中的位置,找到为:pos = 5。

        于是我们就可以确定,整个二叉树的左子树的所有节点,都存在于:[is,pos-1]这个区域。右子树的所有节点都存在于:[pos+1,ie]这个区域。

        接着,我们去创建左子树的根节点,但是左子树的根节点去哪拿呢?我们刚才已经说过,前序遍历优先输出的是每一棵二叉树的根节点。但是我们又如何保证前序序列中哪一个区间的数据 是在左半部分,哪一个区间的数据 是在右半部分呢?

        此时,我们可以定义一个dist来确定左半部分和右半部分的数据。int dist = pos - is。我们可以通过这个差值,在前序序列中确定哪一段区间是属于左子树的,哪一段区间是属于右子树的。

        即:[ps,ps+dist]是下一次查找左子树根节点所在的区间(即左前序,就在这个左前序中查找下一棵二叉树的根节点)
               [is,is+dist-1](即左中序,用于确定下一棵二叉树的左半部分)

               [ps+dist+1,pe]是下一次查找右子树的根节点所在区间(即右前序)

               [is+dis+1,ie]是下一次查找的右中序(用于确定下一棵二叉树的右半部分)

        代码实现

    public void createPI(int[]pre,int[]in){
   
   
        if (pre.length<1 || in.length <1 || pre==null || in==null || pre.length!=pre.length){
   
   
            return;
        }
        int n= pre.length;
        root = createPI(pre,0,n-1,in,0,n-1);
    }
    private BtNode createPI(int[]pre,int ps,int pe,int[]in,int is,int ie){
   
   
        BtNode s = null;
        if (pe-ps>=0){
   
   
            s = new BtNode(pre[ps]);
            int pos = findIn(in,is,ie,pre[ps]);
            if (pos==-1){
   
   
                return null;
            }
            int dist = pos-is;
            s.leftChild = createPI(pre,ps+1,ps+dist,in,is,is+dist-1);
            s.rightChild = createPI(pre,ps+dist+1,pe,in,is+dist+1,ie);
        }
        return s;
    }

    private int findIn(int[]in,int begin,int end,int val){
   
   
        int pos = -1;
        for (int i = begin; i <=end ; i++) {
   
   
            if (in[i] == val){
   
   
                pos = i;
                break;
            }
        }
        return pos;
    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值