首页 > 其他 > 详细

GPLT L2-006 树的遍历

时间:2020-03-14 00:14:21      阅读:70      评论:0      收藏:0      [点我收藏+]

题意:

给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。

思路:

后序遍历确定根结点,中序遍历区分左右子树。

Tips:

注意建树时传根节点的引用。

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

const int M=35;

struct Bt{
    int v;
    Bt *l,*r;
};

int n,a[M],b[M];//a数组储存后序遍历,b数组储存中序遍历 
map<int,int> posa,posb;//某值在后序、中序遍历中的位置

Bt *root;

void build_node(Bt* & pre,int last,int l,int r){//last为根节点的位置,l~r为中序遍历的左右端点
    pre=new(Bt);
    pre->v=a[last];

    int mid=posb[a[last]];//查找在中序遍历的位置
    int last1=-1,last2=-1;
    int l1=l,r1=mid-1;//计算根节点两边区间的端点
    int l2=mid+1,r2=r;

    for(int i=l1;i<=r1;i++)//枚举该子树结点在后序遍历中的位置,最大值即为该子树根节点的位置
        last1=max(last1,posa[b[i]]);
    for(int i=l2;i<=r2;i++)
        last2=max(last2,posa[b[i]]);

    if(l1<=r1)//如果中序遍历区间有效,继续建立子树结点
        build_node(pre->l,last1,l1,r1);
    else
        pre->l=nullptr;
    if(l2<=r2)
        build_node(pre->r,last2,l2,r2);
    else
        pre->r=nullptr;
}

void Print_level(Bt* t){
    queue<Bt*> q;

    cout<<(t->v);
    if(t->l!=nullptr) q.push(t->l);
    if(t->r!=nullptr) q.push(t->r);

    while(!q.empty()){
        Bt* t=q.front();
        q.pop();
        
        if(t!=nullptr){
            cout<< <<(t->v);
            if(t->l!=nullptr) q.push(t->l);
            if(t->r!=nullptr) q.push(t->r);
        }
    }
}

int main()
{
    cin>>n;

    for(int i=0;i<n;i++){
        cin>>a[i];
        posa[a[i]]=i;
    }

    for(int i=0;i<n;i++){
        cin>>b[i];
        posb[b[i]]=i;
    }

    build_node(root,n-1,0,n-1);

    Print_level(root);

    return 0;
}

 优化:

子树的遍历序列是连续的,可以通过计算子树长度,根据原序列端点得出新子序列端点,不必重复枚举序列元素。

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

const int M=35;

struct Bt{
    int v;
    Bt *l,*r;
};

int n,a[M],b[M];//a数组储存后序遍历,b数组储存中序遍历
map<int,int> posb;//后序遍历中某点在中序遍历中的位置

Bt *root;

void build_tree(Bt* & rt,int l1,int r1,int l2,int r2){//l1~r1为该子树的后序遍历,l2~r2为该子树的中序遍历
    if(l1>r1||l2>r2){//若该树不存在有效遍历
        pre=nullptr;
        return;
    }

    rt=new(Bt);
    rt->v=a[r1];//倒数第一个

    int mid=posb[a[r1]];//该端点在中序遍历中的位置
    int len=mid-l2;//左子树的长度

    build_tree(rt->l,l1,l1+len-1,l2,mid-1);//递归建立左子树
    build_tree(rt->r,l1+len,r1-1,mid+1,r2);//递归建立右子树
}

void Print_level(Bt* t){
    queue<Bt*> q;

    cout<<(t->v);
    if(t->l!=nullptr) q.push(t->l);
    if(t->r!=nullptr) q.push(t->r);

    while(!q.empty()){
        Bt* t=q.front();
        q.pop();
        
        if(t!=nullptr){
            cout<< <<(t->v);
            if(t->l!=nullptr) q.push(t->l);
            if(t->r!=nullptr) q.push(t->r);
        }
    }
}

int main()
{
    cin>>n;

    for(int i=0;i<n;i++){
        cin>>a[i];
    }

    for(int i=0;i<n;i++){
        cin>>b[i];
        posb[b[i]]=i;
    }

    build_tree(root,0,n-1,0,n-1);

    Print_level(root);

    return 0;
}

 

GPLT L2-006 树的遍历

原文:https://www.cnblogs.com/Kanoon/p/12489795.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!