树的遍历---pat

根据给定的二叉树后序和中序遍历序列,推导并输出层序遍历序列。同时解析如何利用后序与中序遍历来构造先序遍历序列。示例展示了解题思路和具体步骤。

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

树的遍历 (25分)

给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。
输入格式:
输入第一行给出一个正整数
NN
N(
≤30\le 30
≤30),是二叉树中结点的个数。第二行给出其后序遍历序列。第三行给出其中序遍历序列。数字间以空格分隔。
输出格式:
在一行中输出该树的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。
输入样例:
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
输出样例:
4 1 6 3 5 7 2

已知后序与中序输出前序(先序):
后序:3, 4, 2, 6, 5, 1(左右根)
中序:3, 2, 4, 1, 6, 5(左根右)
分析:因为后序的最后一个总是根结点,令i在中序中找到该根结点,则i把中序分为两部分,左边是左子树,右边是右子树。因为是输出先序(根左右),所以先打印出当前根结点,然后打印左子树,再打印右子树。左子树在后序中的根结点为root – (end – i + 1),即为当前根结点-右子树的个数。左子树在中序中的起始点start为start,末尾end点为i – 1.右子树的根结点为当前根结点的前一个结点root – 1,右子树的起始点start为i+1,末尾end点为end。
输出的前序应该为:1, 2, 3, 4, 5, 6(根左右)

#include<bits/stdc++.h>
using namespace std ;

struct node
{
    int va , pos ;
}la[32];

int main()
{
    queue<node> s;
    int mi[32] , re[32];
    int n ;
    bool vis[32];
    cin >> n ;
    if(n == 0)
        return 0 ;
    for(int i = 1 ; i <= n ; ++ i)
        cin >> la[i].va,la[i].pos=i;
    for(int i = 1 ; i <= n ; ++ i)
        cin >> mi[i],re[mi[i]]=i;
    memset(vis,0,sizeof(vis));
    s.push(la[n]);
    int ans = 1 ;
    while(ans != n)
    {
        node ro = s.front();
        s.pop();
        int cnt = 0 ;
        vis[re[ro.va]] = true ;
        for(int i = re[ro.va]+1 ; i <= n ; i ++)
        {
            if(vis[i] || i > n)
                break ;
            cnt ++ ;
        }

        int cnt2 = 0 ;
         for(int i = re[ro.va]-1 ; i >= 0 ; i --)
        {
            if(vis[i] || i == 0)
                break ;
            cnt2 ++ ;
        }

        if(ro.pos-cnt-1 >= 1 && cnt2 != 0)
            s.push(la[ro.pos-cnt-1]); // 压入左树root

        if(ro.pos-1 >= 1 && cnt != 0)
            s.push(la[ro.pos-1]); // 压入右树root
        ans ++ ;
        printf("%d ",ro.va);
    }
    node last = s.front();
    printf("%d\n",last.va);
    //printf("\n");
    return 0 ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值