1127 ZigZagging on a Tree

1127 ZigZagging on a Tree

题目大意

给出一个树的中序和后序遍历结果,求它的Z字型层序遍历,也就是偶数层从右往左,奇数层从左往右遍历

核心思路

  1. 利用后序序列的下标post_r作为结点编号index,联系数组post和二维数组tree(post[index]为当前结点的值)(tree[index][0]为当前结点的左孩子结点编号,tree[index][1]为当前结点的右孩子结点编号)。经过dfs后,得到存储了每个结点的左右孩子tree[index][0]和tree[index][1]的二维数组tree(每一层dfs中的结点编号index采用引用传递,传递给上一层的tree[index][0]或tree[index][1]或整棵树的根结点root)
  2. 利用结构体node存储这个结点的结点编号index和层号depth;二维数组result存储结点的层号和这一层的所有结点编号(下标为层号,值为这一层的所有结点编号)。经过bfs后将每个结点放到二维数组result中
  3. Z字形输出二维数组
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;

int n;//结点数量
int tree[35][2],root;//记录每个结点的结点编号及其左右孩子的结点编号,根结点编号
vector<int> in,post;//中序序列,后序序列
void dfs(int &index,int in_l,int in_r,int post_l,int post_r){
    if(in_l>in_r) return;//递归边界,表示上一层的结点的该孩子结点编号使用默认值0
    //根结点编号index
    index=post_r;
    //找到当前根结点下标所对应的值在中序序列中的下标
    int i=0;
    while(in[i]!=post[post_r]) i++;
    //根结点编号index所对应的左右孩子结点编号tree[index][0]、tree[index][1]
    dfs(tree[index][0],in_l,i-1,post_l,post_l+(i-in_l)-1);
    dfs(tree[index][1],i+1,in_r,post_l+(i-in_l),post_r-1);    
}
struct node{
    //当前结点的结点编号和所处的层次  
    int index;
    int depth;
};
vector<int> result[35];//二维数组:下标为该结点所处的层次,值为该结点的结点编号
int maxdepth=0;//记录最大的层号
void bfs(){
    queue<node> q;
    q.push(node{root,0});
    while(!q.empty()){
        node temp=q.front();
        result[temp.depth].push_back(temp.index);
        maxdepth=max(maxdepth,temp.depth+1);
        q.pop();
        if(tree[temp.index][0]!=0) q.push(node{tree[temp.index][0],temp.depth+1}); 
        if(tree[temp.index][1]!=0) q.push(node{tree[temp.index][1],temp.depth+1}); 
    }
}

int main(){
    //读入所有的数据
    cin>>n;
    in.resize(n+1),post.resize(n+1);
    for(int i=1;i<=n;i++) cin>>in[i];
    for(int i=1;i<=n;i++) cin>>post[i];
    //dfs深度优先遍历构建树(结点编号使用后序序列的下标表示)
    dfs(root,1,n,1,n);
    //广度优先遍历把每个结点的层号和结点编号放到二维数组result里
    bfs();
    //按照之字形输出
    cout<<post[result[0][0]];
    for(int i=1;i<=maxdepth;i++){
        if(i%2==1){//逆序输出
            for(int j=0;j<result[i].size();j++){
                cout<<" "<<post[result[i][j]];
            }
        }else{//顺序输出
            for(int j=result[i].size()-1;j>=0;j--){
              cout<<" "<<post[result[i][j]];  
            } 
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值