L2-006 树的遍历 (25 分) 树经典问题 给定中序和(先序/后序)重建二叉树
Published on 2022-11-17 23:03 in 暂未分类 with 林动

L2-006 树的遍历 (25 分) 树经典问题 给定中序和(先序/后序)重建二叉树

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

    输入格式:
    输入第一行给出一个正整数N(≤30),是二叉树中结点的个数。第二行给出其后序遍历序列。第三行给出其中序遍历序列。数字间以空格分隔。

    输出格式:
    在一行中输出该树的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。

    输入样例:
    7
    2 3 1 5 7 6 4
    1 2 3 4 5 6 7
    输出样例:
    4 1 6 3 5 7 2

    思路

    后序:左右根 左右根 根
    中序:左根右 根 左根右

    因此后序用来从后向前取得某个子树的根节点,而中序用来提供当前结点对于已建结点的左右孩子关系

    层序遍历需要存储位置信息,不能纯用链式结构,需要数组来存每个结点,由于N=30,所以用数组下标作结点的位置的话极端情况(全在右子树)需要2^30的空间,必定栈溢出,所以使用类似于静态数组的方式,只是对结点加了一个表示位置的的成员,最后再对数组根据位置信息排序,即得到层次序列啦
    更新:层序遍历可以只用链式结构,类似于广搜(我一时没想起来),所以很多做法都行,可以不用数组存储结点,是我太笨了QWQ
    另一种比较好的(递归)解法:https://www.freesion.com/article/2513947642/

    示意图:
    在这里插入图片描述

    ps:其实我觉得还是非递归比较好写

    #include <bits/stdc++.h>
    
    using namespace std;
    
    struct node 
    {
    	int l,r,w,wei;
    } a[50];
    
    int hou[50];
    map<int,int> zon;
    int n,cnt,h=-1;
    
    bool cmp(node a,node b)
    {
    	return a.wei<b.wei;
    }
    
    int main()
    {
    	cin>>n;
    	for(int i=0;i<n;++i)cin>>hou[i];
    	for(int i=0;i<n;++i)
    	{
    		int x;cin>>x;
    		zon[x]=i;
    	}
    	
    	for(int i=n-1;i>=0;--i)
    	{
    		int x=hou[i];
    		if(h==-1)
    		{
    			h=cnt;
    			a[cnt].wei=1;
    			a[cnt++].w=x;
    		}
    		else
    		{
    			int p=h;
    			while(1)
    			{
    				if(zon[x]<zon[a[p].w])
    				{
    					if(a[p].l!=0)
    						p=a[p].l;
    					else 
    					{
    						a[p].l=cnt;
    						a[cnt].wei=a[p].wei*2;
    						a[cnt++].w=x;
    						break;
    					}
    				}
    				else
    				{
    					if(a[p].r!=0)
    						p=a[p].r;
    					else 
    					{
    						a[p].r=cnt;
    						a[cnt].wei=a[p].wei*2+1;
    						a[cnt++].w=x;
    						break;
    					}
    				}
    			}
    		}
    	}
    	sort(a,a+cnt,cmp);
    	for(int i=0;i<cnt;++i)
    		if(i!=cnt-1)cout<<a[i].w<<" ";
    		else cout<<a[i].w;
    
    	return 0;
    }
    

    数组模拟链式结构

        #include <bits/stdc++.h>
        using namespace std;
        const int N=50;
        int hou[N];
        map<int,int> zon;
        int n;
        int w[N],l[N],r[N],cnt=1;
    
        void bfs(){
            queue<int> q;
            q.push(1);
            cout<<w[1];
            while(!q.empty()){
                int t=q.front();q.pop();
                if(t!=1)
                cout<<" "<<w[t];
                if(l[t])q.push(l[t]);
                if(r[t])q.push(r[t]);
            }
        }
        int main()
        {
            cin>>n;
            for(int i=0;i<n;++i)cin>>hou[i];
            for(int i=0;i<n;++i){
                int x;cin>>x;
                zon[x]=i;
            }
    
            for(int i=n-1;i>=0;--i)
            {
                int x=hou[i];
                int dx=zon[x];
                if(cnt==1){
                    w[cnt]=x;
                    cnt++;
                }else {
                    int t=1;
                    while(1){
                        int dy=zon[w[t]];
                        if(dx<dy){
                            if(l[t]==0){
                                l[t]=cnt;
                                w[cnt]=x;
                                cnt++;
                                break;
                            }
                            else t=l[t];
                        }else {
                            if(r[t]==0){
                                r[t]=cnt;
                                w[cnt]=x;
                                cnt++;
                                break;
                            }
                            else t=r[t];
                        }
    
                    }
                }
    
            }
            bfs();
            return 0;
        }
    

    然而实际上这题目只用下标索引左右节点就可以,因为数据并没有打算为难你。。。

    #include <bits/stdc++.h>
    using namespace std;
    const int N=1000005;
    int hou[50];
    map<int,int> zon;
    int n;
    int w[N];
    
    int main()
    {
    	cin>>n;
    	for(int i=0;i<n;++i)cin>>hou[i];
    	for(int i=0;i<n;++i){
    		int x;cin>>x;
    		zon[x]=i;
    	}
    	memset(w,-1,sizeof w);
    	for(int i=n-1;i>=0;--i)
    	{
    		int x=hou[i];
    		int dx=zon[x];
    		if(w[0]==-1){
    			w[0]=x;
    		}else {
    			int t=0;
    			while(1){
    				int dy=zon[w[t]];
    				int l=t*2+1;
    				int r=t*2+2;
    				if(dx<dy){
    					if(w[l]==-1){
    						w[l]=x;
    						break;
    					}else t=l;
    				}else {
    					if(w[r]==-1){
    						w[r]=x;
    						break;
    					}else t=r;
    				}
    			}
    		}
    	}
    	for(int i=0;i<N;++i)
    	{
    		if(w[i]>-1){
    			n--;
    			if(n!=0)cout<<w[i]<<" ";
    			else cout<<w[i];
    		}
    	}
    	return 0;
    }
    
    posted @   林动  阅读(19)  评论(0编辑  收藏  举报
    相关博文:
    阅读排行:
    · 在鹅厂做java开发是什么体验
    · 百万级群聊的设计实践
    · WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
    · 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
    · 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
    点击右上角即可分享
    微信分享提示