括号表示转孩子数组表示法

思路:有一个括号表示的一串序列,假设为A(B,C(Q,E),D),我们发现出现(则表示下面一些元素为(前面一个元素的子女,直到出现),所以们在出现时,就要把之后的元素与他的父亲相连,这里用孩子数组法,也就是父亲节点保存了所有孩子的下标,每次遇到(,就要保存他前一个元素,可以把它压入栈中,然后之后遇到的字母都为该栈顶的子女,直到遇到右括号,用栈的好处就是当括号里还有括号,考虑到就进原则,括号内的元素肯定是最近(前一个元素的子女,栈的思想为先进后出,这样就先考虑后进那个元素的子女,从而实现建树过程,也可以说这是根据前序遍历的思想做的。

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 11111
#define m 3
using namespace std;
typedef struct
{
    char data;
    int child[m];
}node;
typedef struct
{
    node treelist[maxn];
    int len;
}Tree;
/*--------------自定义堆栈-----------------*/
typedef struct
{
    int st[maxn];
    int top;
}Stack;
void Init(Stack &s){s.top=0;}
void Push(Stack &s,int i){s.st[s.top++]=i;}
void Pop(Stack &s){s.top--;}
int Empty(Stack &s){return s.top==0?1:0;}
/*-----------------------------------------*/
void convert(char s[],Tree *t)
{
    int i=0,j=0;
    int len= strlen(s);
    Stack st;
    Init(st);
    for(int k=0;k<m;k++) t->treelist[j].child[k]=-1;
    t->treelist[j].data=s[i];
    j++,i++;
    do
    {
       if(s[i]=='(') Push(st,j-1);//若遇到(,则说明括号内的都为前一个元素的儿子,就把前一个元素的标号压入栈,这里要注意 压入的是是刚建好树的下标
       else if(s[i]==')') Pop(st);//遇到)则说明栈顶元素的子女已经都连接完,就把该元素弹出
            else if(s[i]>='a'&&s[i]<='z'||s[i]>='1'&&s[i]<<'9'||s[i]>='A'&&s[i]<='Z')//如果是数字,字母,就加入树中
            {
              t->treelist[j].data=s[i];//扫到一个元素加入树
              for(int k=0;k<m;k++) t->treelist[j].child[k]=-1;//见该节点的儿子全部初始化为-1
              int l=st.st[st.top-1];//找到栈顶元素,也就是他的父亲节点
              int k=0;
              while(t->treelist[l].child[k]!=-1) k++;//找到父亲节点存放儿子下标的空位
              t->treelist[l].child[k]=j; //下标存入父亲节点
              j++;//对应树的下标要加一
            }
        i++;//源串的下标加一
        //cout<<"s["<<i<<"] "<<s[i]<<endl;
    }while(!Empty(st)&&i<len);//栈为空说明已经连接完成
    t->len=j;
}
void Print(Tree &t)
{
    for(int i=0;i<t.len;i++)
    {
        cout<<t.treelist[i].data<<' ';
        for(int j=0;j<m;j++)
            cout<<t.treelist[i].child[j]<<' ';
        cout<<endl;
    }
}
void preorder(Tree &t,int n)//前序遍历
{
    if(n==t.len) return ;
    cout<<t.treelist[n].data;
    for(int i=0;i<m;i++)
        if(t.treelist[n].child[i]!=-1) preorder(t,t.treelist[n].child[i]);
}
int main()
{
    char s[maxn];
    Tree t;
    while(cin.getline(s,maxn))
    {
        convert(s,&t);
        Print(t);
        preorder(t,0);
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值