uva10410 - Tree Reconstruction BFS和DFS重建树

You have just finished a compiler design homework question whereyou had to find the parse tree of an expression. Unfortunately youleft your assignment in the library, but luckily your friend picked itup for you. Instead of e-mailing you the parse tree so that you canrewrite the solution, your friend decides to play a practical joke andsends you just the DFS and BFS trace. Rather than try to redo theentire question you decide to reconstruct the tree.

Input

The input file contains several test cases as described below.

The first line of a input is the number n (1 <= n<= 1000) of nodes in the tree. The nodes in the tree are numbered1, 2, ...,n. The remaining numbers are the BFStraversal followed by the DFS traversal. Note that when a parent wasexpanded the children were traversed in ascending order.

Output

The output for each case should consist of n lines, one for each node.Each line should start with the node number followed by a colonfollowed by a list of children in ascending order. If there is morethan one solution, any correct answer is acceptable.

Sample Input

8
4 3 5 1 2 8 7 6
4 3 1 7 2 6 5 8

Sample Output

1: 7
2: 6
3: 1 2
4: 3 5
5: 8
6:
7:
8:

  给出树的BFS和DFS,重建树,不一定是二叉树,貌似DFS和BFS顺序要是一样的(以同一个顺序遍历子树)才能做。。

  主要思想还是递归。用vector sub[u]保存u节点的子树的节点,并且按DFS的顺序保存。设build(u,p),u为根节点编号,p为u的下一层在BFS序列中的开始位置。那么u的子节点一定是BFS中在p之后连续的几个节点,并且这些节点出现在u的子节点的DFS中,位置顺序是升序的,也就是在sub[u]中升序出现。那么只要从p到N循环,先找到第一个符合的节点,接着看它之后连续的节点是否符合,若不符合直接break。用vector pos[u][i]保存符合的节点i在sub[u]中的位置,ans[u][i]=b[i]。位置在pos[u][i]和pos[u][i+1]之间的sub中的节点就是ans[u][i]的子节点,把这些节点插入sub[ans[u][i]]就可以递归build(ans[u][i],p+ans[u])。

#include<cstring>
#include<cstdio>
#include<iostream>
#include<climits>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define INF 0x3f3f3f3f
#define MAXN 1010
#define MAXM 1010
using namespace std;
int N,b[MAXN],d[MAXN];
vector<int> sub[MAXN],pos[MAXN],ans[MAXN];
void build(int u,int p){
    int j,prej=-1;        //prej为上一个符合节点在sub[u]中的位置
    int first=1;
    for(int i=p;i<N;i++){
        int find=0;
        for(j=0;j<sub[u].size();j++) if(b[i]==sub[u][j]){
            find=1;
            break;
        }
        if(find&&j>prej){
            first=0;          //已经找到符合的,接下来如果有不符合的就break
            prej=j;
            ans[u].push_back(b[i]);
            pos[u].push_back(j);
        }
        else if(!first) break;
    }
    for(int i=0;i<pos[u].size();i++){
        int n=(i==pos[u].size()-1?sub[u].size():pos[u][i+1]);
        for(int j=pos[u][i]+1;j<n;j++) sub[ans[u][i]].push_back(sub[u][j]);   //插入ans[u][i]的子节点
        build(ans[u][i],p+ans[u].size());
    }
}
int main(){
    freopen("in.txt","r",stdin);
    while(scanf("%d",&N)!=EOF){
        for(int i=0;i<N;i++) scanf("%d",&b[i]);
        for(int i=0;i<N;i++) scanf("%d",&d[i]);
        for(int i=0;i<=N;i++){
            sub[i].clear();
            pos[i].clear();
            ans[i].clear();
        }
        for(int i=1;i<N;i++) sub[b[0]].push_back(d[i]);
        build(b[0],1);
        for(int i=1;i<=N;i++){
            printf("%d:",i);
            for(int j=0;j<ans[i].size();j++) printf(" %d",ans[i][j]);
            puts("");
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值