zoukankan      html  css  js  c++  java
  • GPLT L2-006 树的遍历(二叉树)

    题意:

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

    思路:

    后序遍历序列 = 左子树遍历序列 + 右子树遍历序列 + 根节点。

    中序遍历序列 = 左子树遍历序列 + 根节点 + 右子树遍历序列。

    找到根节点,再利用根节点计算新的后、中遍历序列端点。

    Tips:

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

    #include <bits/stdc++.h>
    using namespace std;
    
    const int M=35;
    int n,a[M],b[M];//a数组储存后序遍历,b数组储存中序遍历
    
    map<int,int> posb;//后序遍历中某点在中序遍历中的位置
    
    struct Bt{//二叉树结点
        int v;
        Bt *l,*r;
    }*root;
    
    void build_tree(Bt* & rt,int l1,int r1,int l2,int r2){//l1~r1为该树的后序遍历序列区间,l2~r2为中序遍历序列区间。
        if(l1>r1||l2>r2){//若不存在有效遍历
            rt=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;
    }

     最初的做法:

    #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;
    }
  • 相关阅读:
    redis五类型及原理|redis主从及问题|Uninstall Redis CentOs 7
    netty4与netty5序列化问题记录
    [转载]【深入Java虚拟机】之四:类加载机制
    序列化原理机制新谈
    [Eclipse使用技巧] Eclipse使用External Tools定位java 源文件目录路径
    学习vue的一些资源
    中国国内可用API合集
    适合初学者学习的的vue+webpack的小项目
    前端性能优化----yahoo前端性能团队总结的35条黄金定律
    Angular2优质学习资源收集
  • 原文地址:https://www.cnblogs.com/Kanoon/p/12489795.html
Copyright © 2011-2022 走看看