树的转换

题目是把一个普通树转化为二叉树,发现用邻接表可以很好地同时表示孩子和兄弟的关系。因为输入用深度优先搜索,采取了同时记录父节点和孩子信息的双向节点结构。

每个节点的格式为 (父亲,自己的编号,孩子)

题目:openjudge 6308

http://jmusoft.openjudge.cn/beida/09/

总时间限制: 
5000ms
内存限制: 
65536kB
描述

我们都知道用“左儿子右兄弟”的方法可以将一棵一般的树转换为二叉树,如:

    0                             0
  / | \                          /
 1  2  3       ===>             1
   / \                           \
  4   5                           2
                                 / \
                                4   3
                                 \
                                  5

现在请你将一些一般的树用这种方法转换为二叉树,并输出转换前和转换后树的高度。

输入
输入包括多行,最后一行以一个#表示结束。
每行是一个由“u”和“d”组成的字符串,表示一棵树的深度优先搜索信息。比如,dudduduudu可以用来表示上文中的左树,因为搜索过程为:0 Down to 1 Up to 0 Down to 2 Down to 4 Up to 2 Down to 5 Up to 2 Up to 0 Down to 3 Up to 0。
你可以认为每棵树的结点数至少为2,并且不超过10000。
输出
对于每棵树,按如下格式输出转换前和转换后树的高度:
Tree t: h1 => h2
其中t是树的编号(从1开始),h1是转换前树的高度,h2是转换后树的高度。
样例输入
dudduduudu
ddddduuuuu
dddduduuuu
dddduuduuu
#
样例输出
Tree 1: 2 => 4
Tree 2: 5 => 5
Tree 3: 4 => 5
Tree 4: 4 => 4


#include <iostream>
#include <cstring>
using namespace std;
typedef struct node{
    int p,num;
    node *ne;
}node;
typedef struct node2{
    int l,r;
}node2;
node tr[10010];
node2 tr2[100010];
void dfs(int i,int d,int &h){
    h=max(h,d);
    if(tr2[i].l!=-1)
        dfs(tr2[i].l,d+1,h);
    if(tr2[i].r!=-1)
        dfs(tr2[i].r,d+1,h);
}
int main(){
    string s;
    cin>>s;
    int n=1;
    while(s!="#"){
        for(int i=0;i<10010;i++){
            tr[i].p=-1;
            tr[i].num=i;
            tr[i].ne=NULL;
        }
        int t=0,tm=0;
        node *p,*q;
        int count=0,c=0;;
        for(int i=0;i<s.length();i++){
            if(s[i]=='d'){
                p=&tr[tm];
                while(p->ne!=NULL){
                    p=p->ne;
                }
                q=new node;
                q->p=tm;
                q->num=++t;
                q->ne=NULL;
                p->ne=q;
                tr[t].p=tm;
                tm=t;
                c++;
            }else{
                tm=tr[tm].p;
                c--;
            }
            count=max(count,c);
        }
        memset(tr2,-1,sizeof(tr2));
        for(int i=0;i<=t;i++){
            p=tr[i].ne;
            if(p!=NULL){
               tr2[i].l=p->num;
            int j=p->num;
            while(p->ne!=NULL){
                p=p->ne;
                while(tr2[j].r!=-1){
                    j=tr2[j].r;
                }
                tr2[j].r=p->num;
            }
            }
        }
        int h=0;
        dfs(0,0,h);
        cout<<"Tree "<<n++<<": "<<count<<" => "<<h<<endl;
        cin>>s;
    }
    return 0;
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值