数据结构系列(六)-广义表

本篇介绍数据结构-广义表

思维导图

数据结构系列(六)-广义表_第1张图片

广义表

广义表是线性表的推广,又称列表。是 n(n≥0)个元素 a1 ,a2 ,…,ai ,…,an 的有限序列。

广义表通常记作:Ls=( a1 ,a2 ,…,ai ,…,an ):
    1.Ls 是广义表的名字,n为它的长度;
    2.为了区分原子和广义表,书写时用大写字母表示广义表,用小写字母表示原子。
    3.若广义表 Ls非空(n≥1),则 al是 LS的表头,其余元素组成的表(a1 ,a2 ,…,an )称为Ls的表尾。
    4.广义表是递归定义的;

性质:
    1.广义表的元素可以是子表,而子表又可以含有子表,因此广义表是一个多层次结构的表;
    2.广义表具有递归和共享的性质;
  • 例子

      A=()-A是一个空表,其长度为零;
      B=(a)-B是一个只有一个原子的广义表,其长度为1;
      C=(a,(b,c))-C是一个长度为2的广义表,第一元素是原子,第二个元素是子表;
      D=(A,B,C)=((),(a),(a,(b,c)))-D是一个长度为3的广义表,其中三个元素是子表;
      E=(C,d)=((a,(b,c)),d)-E是一个长度为2的广义表,第一个元素是子表,第二个元素是原子;
      F=(e,F)=(e,(e,(e,...)))-F是一个递归的表,它的长度为2,第一个元素是原子,第二个元素是表自身,展开后它是一个无限的广义表;
    

    数据结构系列(六)-广义表_第2张图片

广义表的存储结构

数据结构系列(六)-广义表_第3张图片

tag是一个标志位,用来区分当前结点是原子还是子表;
当tag为零值时,该结点是子表;第二个域为slink,用以存放子表的地址;

当tag为1时,该结点是子表;第二个域为data,用以存放元素值。link域是用来存放与本元素同一层的下一个元素对应结点的地址,当该元素是所在层的最后一个元素时,link的值为NULL。

广义表的基本运算

  • 建立广义表的存储结构

      Glist CreatGList(Glist GL){
          char ch;
          scanf("%c",&ch);
          if(ch!=''){
              GL=(GLNode *)malloc(sizeof(GLNode));
              if(ch=='('){
                  GL->tag=list;
                  GL->slink=CreatGList(GL->slink);//递归调用的构造子表
              }else{ //构造原子结点
                  GL->tag=atom;
                  GL->data=ch;
              }
          }else GL=NULL;
          scanf("%c",&ch);
          if(GL!=NULL)
          if(ch==","){
              GL->link=CreatGList(GL->link); //递归构造后续广义表
          }else{
              GL->link=NULL; //表示遇到‘)’或结束符‘;’时,无后续表
          }
          return GL
      }
    
  • 输出广义表

      void PrintGList(Glist GL){
          if(GL!=NULL){
              if(GL->tag==list){
                  printf("(");
                  if(GL->slink==NULL)
                      printf(" ");
                  else
                      PrintfGList(GL->slink); //递归调用输出子表
              }else 
                  printf("%c",GL->data); //输出结点数据域值
              if(GL->tag==list)
                  printf(")");
              if (GL->link!=NULL){
                  printf(",");
                  PrintfGList(GL->link); //递归调用输出下一个结点
              }
          }
      }
    
  • 广义表的查找

      void FindGListX(GList GL,DataType x,int *mark){
          if(GL!=NULL){
              if(GL->tag==0 && GL->data==x){
                 p=GL;
                 *mark=1;
              }else{
                  if(GL->tag==1)
                     FindGListX(GL->slink,x,mark);
                 FindGListX(GL->link,x,mark);
              }
          }
      }
    
  • 求广义表表头

     Glist head(Glist GL){
         Glist p;
         if(GL!=NULL && GL->tag!=0){
             p=GL->slink;
             p->link=NULL;
             return p;
         }else
             return NULL;
     }
    
  • 求广义表表尾

     Glist tail(Glist GL){
         Glist p;
         if(GL!=NULL && GL->tag!=0){
             p=GL->slink;
             p=p->link;
             GL->slink=p;
         }
         return p;
     }
    
  • 求广义表的深度

      void depth(Glist GL,int *maxdh){
          int h;
          if(GL->tag==0) 
              *maxdh=0;  //说明广义表尾单个元素
          else
              if(GL->tag==1 && GL->slink==NULL)
                  *maxdh=1;  //广义表为空表
              else //进行递归求解
                  GL=GL->slink;  //进入第一层
                  *maxdh=0;
                  do{  //循环扫描表的第一层的每个结点,对每个结点求其子表深度
                      depth(GL,&h);
                      if(h>*maxdh) *maxdh=h;  //取最大的子表深度
                          GL=GL->link;
                  }while(GL!=NULL);
                  *maxdh=*maxdh+1; //子表最大深度加
      }
    

你可能感兴趣的:(数据结构)