(dfs)-树的括号表示法

本文介绍了一种使用括号表示法表示二叉树的方法,该方法由HOME_W发明,能够保留二叉树的先序遍历顺序并存储树结构。文章详细解释了递归定义,并通过一个例子展示了如何将二叉树转换为括号表示法,最后提供了一个算法实现,使用深度优先搜索(DFS)来输出二叉树的括号表示。
摘要由CSDN通过智能技术生成

树的括号表示法

TimeLimit:1000MS  MemoryLimit:128MB

64-bit integer IO format:%lld

已解决 | 点击收藏

×

收藏题目

备注

 

Close确定

Problem Description

HOME_W发明了一种括号表示法来表示二叉树结构

他的递归定义如下,

  • 若结点v有左孩子或者右孩子,且左右子树的括号表示分别为A,B。则结点v的括号表示法为 v(A,B)

  • 否则 空树用#表示,只有一个结点v的树的括号表示法就是 v

例如树

         1

       /  \

     2     3

   /

 4

的括号表示法是

1(2(4,#),3)

这种表示法有些优越之处,既保留了二叉树的先序遍历顺序,又存贮了树的结构。方便了树结构在网络上的传输,且解析时甚至不需要重新建立这颗树

 

现在给你一颗以1为根的二叉树的所有边,请输出这棵树的括号表示法

Input

单组数据

第一行是一个整数n,代表树的结点数。

接下来有n-1行,每行有两个整数a,b代表的a,b之间有一条边。

n<=1e5

1<=a,b<=n

保证输入是一颗合法的二叉树

Output

请输出一行,代表这棵树的括号表示法,由于输出结果可能不唯一,请输出字典序最小的方案

题意修正:这里的字典序是只比较整个数字和#号的

其中大小关系如下:#<1<2<3<……<10<11<……<100<101<……

SampleInput

2 1 2

SampleOutput

1(#,2)

Submit

题解:DFS

#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<bitset>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#define eps (1e-8)
#define MAX 0x3f3f3f3f
#define u_max 1844674407370955161
#define l_max 9223372036854775807
#define i_max 2147483647
#define re register
#define pushup() tree[rt]=tree[rt<<1]+tree[rt<<1|1]
using namespace std;

inline int read(){
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' & c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}

typedef long long ll;
const double pi = atan(1.)*4.;
const int M=4e5+5;
const int N=2e6+5;
vector<int>v[M];
int vv[M];
int f[N],p=0;
void dfs(int x){
    f[p++]=x;
    if(x!=0)
       vv[x]=1;
    f[p++]=N;       // N 代表左括号
    for(int i=0;i<v[x].size();i++){
        if(vv[v[x][i]]) continue;
        dfs(v[x][i]);
    }
    f[p++]=N+1;   // N+1 代表右括号
}
int main(){
    int n,a,b;
    scanf("%d",&n);
    if(n==1){
        printf("1\n");
        return 0;
    }
    int m=n-1;
    for(int i=0;i<m;i++){    // 建图
        scanf("%d %d",&a,&b);
        v[a].push_back(b);
        v[b].push_back(a);
    }
    // 先弄成满二叉树
    if(v[1].size()==1) v[1].push_back(0);      //  0 代表空值     
    for(int i=2;i<=n;i++){
        if(v[i].size()==1||v[i].size()==0) continue;
        if(v[i].size()==2) v[i].push_back(0);
    }
    for(int i=1;i<=n;i++)  sort(v[i].begin(),v[i].end());
    dfs(1);
     int i=0;
    while(i<p){
        if(f[i]>0&&f[i]<N){
            printf("%d",f[i]);
            i++;
        }
        else if(f[i]==0){
            printf("#");
            i++;
        }
        else if(f[i]==N&&f[i+1]==N+1){
            if(f[i+2]!=N+1)
                printf(",");
            i=i+2;
        }
        else if(f[i]==N&&f[i+1]!=N+1){
            printf("(");
            i++;
        }
        else if(f[i]==N+1){
            if(i!=p-1){
                if(f[i+1]!=N+1)
                    printf("),");
                else
                    printf(")");
            }
            else{
                printf(")");
            }
            i++;
        }
    }
    return 0;
}

 

题目描述 表示方法有多种,如图6_1采用的就是一种形象的表示法;另外还有一种常用的表示方法"括号表示法",它的表示方法归纳如下:先将整棵的根结点放入一对圆括号中,然后把它的子由左至右放入括号中,同层子用圆括号括在一起(同层子之间用逗号隔开),而对子也采用同样的方法处理,直到所有的子都只有一个根结点为止。用括号表示法表示图6_1的步骤如下: =(T) =(1(T1,T2 ,T3 )) {1是根结点,有3棵子,用逗号隔开} =(1(2(T11,T12),3,4(T31))) {分别对3棵子做同样的操作} =(1(2(5,6),3,4(7(T311,T312)))) =(1(2(5,6),3,4(7(8,9)))) 实际上,以上方法是按照的层次逐步展开,直到所有结点都已列出。 注意,当一个节点有若干个子时,子节点编号小的写在前面,编号大的写在后面。 给你一棵n个节点的有根,节点标号为1~n,1号节点为根节点。 请给出它的括号表示结果。 输入 第一行一个整数n。 以后n行,每行若干个整数。第i行,第一个数为mi,表示节点i的子节点个数。紧接着mi个整数,表示节点i子节点的编号。保证父节点编号小于子节点。 输出 一行一个字符串,由数字、括号、逗号组成。表示括号表示的结果。注意不包含多余空格。 样例 输入 3 2 2 3 0 0 输出 (1(2,3)) 请用c++语言编码
07-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值