pat 甲级 1020 Tree Traversals

这道题的思路是先构建二叉树,然后层序遍历二叉树。将问题拆解:1.如何构建二叉树。2.如何测层序遍历二叉树。

1.构建二叉树
首先我们要知道一棵二叉树可由它的中序遍历和后序遍历确定:
(1)后序遍历的最后是该树或子树的根
(2)中序遍历根的左右分左子树和右子树

通过后序遍历找到根的值,然后再到中序序列里找到根的位置再将该树分为左子树与右子树 。不断递归即可通过中序和后序重塑一棵树。

int build(int il,int ir,int pl,int pr)//il,ir为中序遍历的左右下标;pl,pr为后序遍历的下标
{
    int root=postorder[pr]; //后序遍历的最后一位是树的根
    int k=pos[root];//pos数组记录了每个数的下标
    //根将中序遍历分成两部分,分别是左子树、右子树
    //l,r 为map,记录左右子树。
    if(il<k) l[root]=build(il,k-1,pl,k-1-il+pl);//k-1-il=x-pl  //左子树在中序序列中为[il,k-1] ,在后序序列中左子树长度相同,从pl开始,故 x-pl=k-1-il,x即右端点为k-1-il+pl;
    if(k<ir) r[root]=build(k+1,ir,pr-ir+k,pr-1);// pr-1-x=ir-k-1 //右子树在中序序列中为[k+1,ir] ,在后序序列中右子树长度相同,到pr-1结束,故 pr-1-x=ir-k-1,x即左端点为pr-ir+k;
    return root;
}

2.bfs层序遍历树

void bfs(int root)
{
    queue<int> q; 
    q.push(root);
    int flag=1;//标记是否第一次输出,第一次输出数组,后续输出空格数字;为了最后数字没有输出空格(pat格式要求)
    while(q.size()){
        int x=q.front();
        q.pop();
        if(flag){
            cout<<x;
            flag=0;
        }
        else cout<<" "<<x;
        if(l.count(x)) q.push(l[x]);//如果左节点在,则放入队列
        if(r.count(x)) q.push(r[x]);//如果有右节点,则放入队列
    }
}

整体代码:

#include<iostream>
#include<algorithm>
#include<string>
#include<unordered_map>
#include<queue>

using namespace std;
const int N=40;
int postorder[N],inorder[N];
unordered_map<int,int> l,r,pos;
int build(int il,int ir,int pl,int pr)
{
    int root=postorder[pr];
    int k=pos[root];
    if(il<k) l[root]=build(il,k-1,pl,k-1-il+pl);//k-1-il=x-pl
    if(k<ir) r[root]=build(k+1,ir,pr-ir+k,pr-1);// pr-1-x=ir-k-1
    return root;
}
void bfs(int root)
{
    queue<int> q;
    q.push(root);
    int flag=1;
    while(q.size()){
        int x=q.front();
        q.pop();
        if(flag){
            cout<<x;
            flag=0;
        }
        else cout<<" "<<x;
        if(l.count(x)) q.push(l[x]);
        if(r.count(x)) q.push(r[x]);
    }
}
int main()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++) cin>>postorder[i];
    for(int i=0;i<n;i++){
        cin>>inorder[i];
        pos[inorder[i]]=i;//pos存放每个数的下标
    }
    int root=build(0,n-1,0,n-1);//构建二叉树
    bfs(root);//层序遍历
    return 0;
}