zoukankan      html  css  js  c++  java
  • 【数据结构】广义表

      1 #include <stdio.h>  
      2 #include <malloc.h>  
      3 #include <stdlib.h>  
      4 #include <string.h>  
      5 #define MAXSTRLEN 40 )  
      6 typedef char SString[MAXSTRLEN+1];   
      7 typedef char AtomType;                     // 定义原子类型为字符型    
      8 typedef enum{  
      9     ATOM, LIST                            // ATOM==0:原子 LIST==1:子表                       
     10 } ElemTag;   
     11   
     12 typedef struct GLNode  
     13 {  
     14     ElemTag tag;                // 公共部分,用于区分原子结点和表结点   
     15     union                               // 原子结点和表结点的联合部分   
     16     {  
     17         AtomType atom;                      // atom是原子结点的值域, AtomType由用户定义   
     18         struct  
     19         {  
     20             struct GLNode *hp,*tp;  
     21         }ptr;                                // ptr是表结点的指针域,prt.hp和ptr.tp分别指向表头和表尾   
     22     }a;  
     23 } *GList, GLNode;     
     24   
     25   
     26 //初始化的广义表L  
     27 int InitGList(GList *L)  
     28 {   
     29     *L = NULL;  
     30     return 1;  
     31 }  
     32   
     33 //销毁广义表L  
     34 void DestroyGList(GList *L)   
     35 {   
     36     GList q1,q2;  
     37     if(*L)  
     38     {  
     39         if((*L)->tag == ATOM)  
     40         {  
     41             free(*L);                                 
     42             *L = NULL;  
     43         }  
     44         else      
     45         {  
     46             q1 = (*L)->a.ptr.hp;  
     47             q2 = (*L)->a.ptr.tp;  
     48             free(*L);  
     49             *L = NULL;  
     50             DestroyGList(&q1);  
     51             DestroyGList(&q2);                      // 递归删除表头和表尾结点  
     52           
     53         }  
     54     }  
     55 }  
     56   
     57   
     58 // 采用头尾链表存储结构,由广义表L复制得到广义表T。   
     59 int CopyGList(GList *T,GList L)  
     60 {  
     61     if(!L)  
     62         *T = NULL;  
     63     else  
     64     {  
     65         *T = (GList)malloc(sizeof(GLNode));   
     66         if(!*T)  
     67             exit(0);  
     68         (*T)->tag = L->tag;  
     69         if(L->tag == ATOM)  
     70             (*T)->a.atom = L->a.atom;                             // 复制单原子   
     71         else                                                // 是表结点,则依次复制表头和表尾  
     72         {  
     73             CopyGList(&((*T)->a.ptr.hp), L->a.ptr.hp);  
     74             CopyGList(&((*T)->a.ptr.tp), L->a.ptr.tp);  
     75                                                           
     76               
     77         }  
     78     }  
     79     return 1;  
     80 }  
     81   
     82 // 返回广义表的长度,即元素个数  
     83 int GListLength(GList L)  
     84 {  
     85     int len = 0;  
     86     if(!L)  
     87         return 0;  
     88     if(L->tag == ATOM)  
     89         return 1;  
     90     while(L)  
     91     {  
     92         L = L->a.ptr.tp;   
     93         len++;  
     94     }  
     95     return len;  
     96 }  
     97   
     98   
     99 // 采用头尾链表存储结构,求广义表L的深度。  
    100 int GListDepth(GList L)  
    101 {  
    102     int max, dep;  
    103     GList pp;  
    104       
    105     if(!L)  
    106         return 1;                                                                   // 空表深度为1  
    107     if(L->tag == ATOM)  
    108         return 0;                                                                           // 原子深度为0  
    109     for(max = 0, pp = L; pp; pp = pp->a.ptr.tp)  
    110     {  
    111                                                                                     // 递归求以pp->a.ptr.hp为头指针的子表深度   
    112         dep = GListDepth(pp->a.ptr.hp);  
    113         if(dep > max)  
    114             max = dep;  
    115     }  
    116     return max+1;                                                           // 非空表的深度是各元素的深度的最大值加1   
    117 }  
    118   
    119 // 判定广义表是否为空  
    120 int GListEmpty(GList L)  
    121 {  
    122     if(!L)  
    123         return 1;  
    124     else  
    125         return 0;  
    126 }  
    127   
    128 // 取广义表L的头  
    129 GList GetHead(GList L)  
    130 {  
    131     GList h,p;  
    132   
    133     if(!L)  
    134     {  
    135         printf("空表无表头!
    ");  
    136         exit(0);  
    137     }  
    138     p = L->a.ptr.tp;   
    139     L->a.ptr.tp = NULL;  
    140     CopyGList(&h,L);  
    141     L->a.ptr.tp = p;  
    142     return h;  
    143 }  
    144   
    145 // 取广义表L的尾  
    146 GList GetTail(GList L)  
    147 {  
    148     GList t;  
    149     if(!L)  
    150     {  
    151         printf("空表无表尾!
    ");  
    152         exit(0);  
    153     }  
    154     CopyGList(&t, L->a.ptr.tp);  
    155     return t;  
    156 }  
    157   
    158   
    159   
    160 // 插入元素e作为广义表L的第一元素(表头,也可能是子表)   
    161 int InsertFirst_GL(GList *L,GList e)  
    162 {  
    163     GList p = (GList)malloc(sizeof(GLNode));  
    164     if(!p)  
    165         exit(0);  
    166     p->tag = LIST;  
    167     p->a.ptr.hp = e;  
    168     p->a.ptr.tp = *L;  
    169     *L = p;  
    170     return 1;  
    171 }  
    172   
    173   
    174   
    175 // 删除广义表L的第一元素,并用e返回其值  
    176 int DeleteFirst_GL(GList *L,GList *e)  
    177 {   
    178     GList p;  
    179     *e = (*L)->a.ptr.hp;   
    180     p = *L;  
    181     *L = (*L)->a.ptr.tp;   
    182     free(p);  
    183     return 1;  
    184 }  
    185   
    186   
    187   
    188 // 利用递归算法遍历广义表L   
    189 void Traverse_GL(GList L,void(*v)(AtomType))  
    190 {  
    191     if(L)   
    192         if(L->tag == ATOM)  
    193             v(L->a.atom);  
    194         else  
    195         {  
    196             Traverse_GL(L->a.ptr.hp,v);  
    197             Traverse_GL(L->a.ptr.tp,v);  
    198         }  
    199 }  
    200   
    201 // 生成一个其值等于chars的串T  
    202 int StrAssign(SString T,char *chars)  
    203 {   
    204     int i;  
    205     if(strlen(chars) > MAXSTRLEN)  
    206         return 0;  
    207     else  
    208     {  
    209         T[0] = strlen(chars);  
    210          for(i = 1; i <= T[0]; i++)  
    211             T[i] = *(chars + i - 1);  
    212         return 1;  
    213     }  
    214 }  
    215   
    216 // 由串S复制得串T  
    217 int StrCopy(SString T, SString S)  
    218 {  
    219     int i;  
    220     for(i = 0; i <= S[0]; i++)  
    221         T[i] = S[i];  
    222     return 1;  
    223 }  
    224   
    225   
    226 // 若S为空串,则返回1,否则返回0   
    227 int StrEmpty(SString S)  
    228 {  
    229     if(S[0] == 0)  
    230         return 1;  
    231     else  
    232         return 0;  
    233 }  
    234   
    235   
    236   
    237 // 若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0   
    238 int StrCompare(SString S,SString T)  
    239 {  
    240     int i;  
    241     for(i = 1; i <= S[0] && i <= T[0]; ++i)  
    242         if(S[i] != T[i])  
    243             return S[i] - T[i];  
    244     return S[0]-T[0];  
    245 }  
    246   
    247 // 返回串的元素个数  
    248 int StrLength(SString S)  
    249 {  
    250     return S[0];  
    251 }  
    252   
    253 // 将S清为空串  
    254 int ClearString(SString S)  
    255 {  
    256     S[0] = 0;   // 令串长为零  
    257     return 1;  
    258 }  
    259   
    260   
    261 // 用Sub返回串S的第pos个字符起长度为len的子串。  
    262 int SubString(SString Sub,SString S,int pos,int len)  
    263 {   
    264     int i;  
    265     if(pos < 1 || pos >S[0] || len < 0 || len > S[0]-pos+1)  
    266         return 0;  
    267     for(i = 1; i <= len; i++)  
    268         Sub[i]=S[pos+i-1];  
    269     Sub[0] = len;  
    270     return 1;  
    271 }  
    272   
    273   
    274 // 将非空串str分割成两部分:hsub为第一个','之前的子串,str为之后的子串   
    275 void sever(SString str,SString hstr)   
    276 {  
    277     int n,i, k;    
    278     SString ch,c1,c2,c3;  
    279     n = StrLength(str);  
    280     StrAssign(c1,",");  
    281     StrAssign(c2,"(");  
    282     StrAssign(c3,")");  
    283     SubString(ch,str,1,1);  
    284     for(i = 1,k = 0;i <= n && StrCompare(ch,c1) || k != 0; ++i)  
    285     {   
    286         SubString(ch, str, i, 1);  
    287         if(!StrCompare(ch, c2))  
    288             ++k;  
    289         else if(!StrCompare(ch,c3))  
    290             --k;  
    291     }  
    292     if(i <= n)  
    293     {  
    294         SubString(hstr, str, 1, i-2);  
    295         SubString(str, str, i, n - i + 1);  
    296     }  
    297     else  
    298     {  
    299         StrCopy(hstr, str);  
    300         ClearString(str);  
    301     }  
    302 }  
    303   
    304   
    305 // 广义表L。设emp="()"   
    306 int CreateGList(GList *L, SString S)  
    307 {  
    308     SString sub,hsub,emp;  
    309     GList p,q;  
    310       
    311     StrAssign(emp,"()");  
    312     if(!StrCompare(S, emp))  
    313         *L = NULL;  // 创建空表   
    314     else  
    315     {  
    316         *L = (GList)malloc(sizeof(GLNode));  
    317         if(!*L)     // 建表结点   
    318             exit(0);  
    319         if(StrLength(S) == 1)   // S为单原子   
    320         {  
    321             (*L)->tag = ATOM;  
    322             (*L)->a.atom = S[1]; // 创建单原子广义表   
    323         }  
    324         else  
    325         {  
    326             (*L)->tag = LIST;  
    327             p = *L;  
    328             SubString(sub, S, 2, StrLength(S)-2); // 脱外层括号   
    329             do  
    330             {   // 重复建n个子表   
    331                 sever(sub, hsub); // 从sub中分离出表头串hsub   
    332                 CreateGList(&p->a. ptr. hp, hsub);  
    333                 q = p;  
    334                 if(!StrEmpty(sub))  // 表尾不空   
    335                 {  
    336                     p = (GLNode *)malloc(sizeof(GLNode));  
    337                     if(!p)  
    338                         exit(0);  
    339                     p->tag = LIST;  
    340                     q->a.ptr.tp = p;  
    341                 }  
    342             }while(!StrEmpty(sub));  
    343             q->a.ptr.tp = NULL;  
    344         }  
    345     }  
    346     return 1;  
    347 }  
    348   
    349 // 打印原子   
    350 void visit(AtomType e)  
    351 {  
    352     printf("%c ", e);  
    353 }  
    354   
    355 int main()  
    356 {  
    357     // 广义表的表示形式是,空表:(),单原子:a,表:(a,(b),c,(d,(e)))   
    358     char p[80] = {"(a,(b),c,(d,(e)))"};  
    359     SString t;  
    360     GList L,m;  
    361       
    362     InitGList(&L);  
    363     InitGList(&m);  
    364     printf("空广义表L的深度 = %d
    L是否空?%d(1:是 0:否)
    
    ",  
    365         GListDepth(L), GListEmpty(L));  
    366     StrAssign(t, p);  
    367     CreateGList(&L, t);                                         // 创建广义表   
    368     printf("
    广义表L的长度 = %d
    ", GListLength(L));  
    369     printf("广义表L的深度 = %d 
    L是否空?%d(1:是 0:否)
    ",  
    370         GListDepth(L), GListEmpty(L));  
    371     printf("遍历广义表L:
    ");  
    372     Traverse_GL(L, visit);  
    373     printf("
    
    复制广义表m = L
    ");  
    374     CopyGList(&m, L);  
    375     printf("广义表m的长度 = %d
    ", GListLength(m));  
    376     printf("广义表m的深度 = %d
    ", GListDepth(m));  
    377     printf("遍历广义表m:
    ");  
    378     Traverse_GL(m,visit);  
    379     DestroyGList(&m);  
    380     m = GetHead(L);  
    381     printf("
    
    m是L的表头,遍历广义表m:
    ");  
    382     Traverse_GL(m, visit);  
    383     DestroyGList(&m);  
    384     m = GetTail(L);  
    385     printf("
    
    m是L的表尾,遍历广义表m:
    ");  
    386     Traverse_GL(m,visit);  
    387     InsertFirst_GL(&m, L);  
    388     printf("
    
    插入L为m的表头,遍历广义表m:
    ");  
    389     Traverse_GL(m,visit);  
    390     printf("
    
    删除m的表头,遍历广义表m:
    ");  
    391     DestroyGList(&L);  
    392     DeleteFirst_GL(&m, &L);  
    393     Traverse_GL(m, visit);  
    394     printf("
    ");  
    395     DestroyGList(&m);  
    396     return 0;  
    397 }  
  • 相关阅读:
    #Laravel笔记# 使用SMTP发送邮件功能
    #Laravel笔记# 监听事件
    idea 常见问题
    python常见函数汇总
    双DNN排序模型:在线知识蒸馏在爱奇艺推荐的实践
    机器学习算法GBDT
    Hive表数据同步到es
    目标检测资料
    zeppelin的介绍与使用
    Java汉字获取拼音、笔划、偏旁部首
  • 原文地址:https://www.cnblogs.com/duolaAbao/p/6723974.html
Copyright © 2011-2022 走看看