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

    1. 广义表的定义
         每个元素可以为Atom,原子,也可以为线性表。
         线性表的推广。线性表元素有唯一的前驱和后继,为线性表,而广义表是多层次的线性表
         表头:第一个元素,可能是原子,可能是广义表
         表尾:除了第一个元素,剩余的元素,所构成的广义表
         举例:
             A = (a,b,(c,d),e)
             head(A)  = a
             tail(A) = (b,(c,d),e)
         遍历操作:
         取表头,取表尾 ,取表头..
         长度:最外层的元素数,即最外层的','+1
         深度:括号层数
      2. 广义表的两种存储结构(子表法)
     
          2.1链式存储结构 - 每个数据元素可以用一个节点表示
             元素可以为原子或列表
             原子节点:标志域、值域
             列表节点:标志域、指示表头的指针域、指示表尾的指针域
             空表:A = NULL
             除了空表,表头指针指向一个表节点,表节点再分表头、表尾...
             最高层表节点(可能原子、子表)的个数就是表长度? A = (a,b,(c,d),e) 最高层表头是先a,表尾是(b,(c,d),e),表头是b,表尾((c,d),e)..就是第一层的表尾直到为空之前,有过的表尾指针+1
             判断是否在同一层次?
                 是这样的: 最高层处于同一层,后继的tail指针指向的是同一层,否则,head指针,或者表头是Atom,都是下一层。
         2.2扩展线性表存储结构
             不是用表头表尾指针了,而是,每一个节点,不管是子表还是原子,都有一个指向本子表下一个元素的next指针
             A = (a,b,(c,d))
             A -> |1,HP,TP|
                     |    |
                     a -> b -> (c,d)
                                 |
                                 c -> d

    下面,实现了广义表的两种定义,以及基于递归的一些操作。

      1 #include<bits/stdc++.h>
      2 #define AtomType int
      3 typedef enum{ATOM,LIST}ElemTag; //ATOM = 0:原子;LIST = 1:子表 
      4 /*线性表存储之链式*/
      5 typedef struct GLNode{
      6     ElemTag tag; //枚举类型的标志域,只能取定义了的枚举值
      7     union{      //union联合体,下面两部分只能取其一;要么取AtomType;要么取结构体ptr,ptr包括两个指针hp,tp 
      8         AtomType atom;
      9         struct{
     10             struct GLNode *hp,*tp;
     11         }ptr;
     12     }; 
     13 }*GList; //定义广义表类型,GList为指针 
     14 
     15 /*线性表存储之扩展线性表 = 子表法*/ 
     16 typedef struct GLNode2{
     17     ElemTag tag;
     18     union{
     19         AtomType atom;
     20         struct GLNode2 *hp;     //对于原子,tp就是指向其相同层次的下一个元素 
     21                              //对于列表,hp指向本列表内部第一个元素,而tp是指向本层次上的下一个元素 
     22     };
     23     struct GLNode2 *tp;
     24 } *GList2;
     25 /*
     26 *    讨论广义表的递归算法 : 分治法进行递归算法设计
     27 *    1. 问题可拆解成子问题,与原问题性质相同,规模变小
     28 *    2. 有递归终止条件 
     29 */ 
     30 
     31 /*求广义表的深度 - 采用链式存储结构时 
     32 *    广义表的深度:()的重数  空表() 深度为1.原子深度为0 
     33 *    
     34 */
     35 int GListDepth(GList L) {
     36     if(!L) return 1; //空表1
     37     if(L->tag ==ATOM ) return 0;
     38     GList pp;
     39     //遍历同一层,递归下一层,取表尾,取表头,第一步先去一个表头 
     40     int max;
     41     for(max = 0, pp =L;pp!=NULL;pp = pp->ptr.tp){
     42         int dep = GListDepth(pp->ptr.hp) ;
     43         if(dep > max) max = dep; //这一步比较,是比较同一层的depth 
     44     }
     45     return max+1;
     46 }
     47 //练习
     48 int depth_my(GList L) {
     49     if(L == NULL){
     50         return 1;
     51     }
     52     if(L->tag == ATOM){
     53         return 0;
     54     }
     55     int max = 0;
     56     GList pp;
     57     for(max = 0,pp=L;pp!=NULL;pp = pp->ptr.tp){
     58         int dep = depth_my(pp->ptr.hp);
     59         if(dep >max) max = dep;
     60     }
     61     return max+1;
     62 }
     63 
     64 /*
     65     求Depth2 == 子表法求dep 
     66 */
     67 int GListDepth_2(GList2 L){
     68     if(L == NULL) return 1;
     69     if(L->tag == ATOM) return 0;
     70     int max = 0;
     71     GList2 pp;
     72     for(max = 0,pp=L->hp;pp!=NULL;pp = pp->tp){
     73         int dep = GListDepth_2(pp);
     74         if(dep >max) max = dep;
     75     }
     76     return max+1;
     77 }
     78 /*********************分界*****************************/
     79 /*
     80 *    复制广义表:copy深复制 -- 链式存储 
     81 *    分别复制表头、表尾,然后合成即可==递归 
     82 */
     83 void CopyGList(GList &T,GList L) { 
     84     //头尾链表存储,将L赋值给T 
     85     if(!L) T = NULL; //
     86     else{
     87         //创建一个节点 ,这个节点要么是ATOM,要么是广义表 
     88         T = (GList)malloc(sizeof(GLNode));
     89         if(!T) exit(0);
     90         T->tag = L->tag;
     91         if(L->tag == ATOM) //是原子的话,复制原子 
     92             T->atom = L->atom; 
     93         //复制广义表
     94         else{
     95             //分别复制表头和表尾 
     96             CopyGList(T -> ptr.hp,L->ptr.hp);
     97             CopyGList(T->ptr.tp,L->ptr.tp);
     98         } 
     99     }
    100 }
    101 //练习
    102 void copy_my(GList&T,GList L) {
    103     if(L == NULL) T = NULL;
    104     else{
    105         T = (GList)malloc(sizeof(GLNode));
    106         if(!T) exit(0);
    107         T -> tag = L -> tag;
    108         if(L->tag == ATOM){
    109             T->atom = L->atom;
    110         }else{
    111             copy_my(T -> ptr.hp,L->ptr.hp);
    112             copy_my(T ->ptr.tp,L->ptr.tp);
    113         }
    114     }
    115 }
    116 /**********************分割线*************************/
    117 /*
    118 *    创建一个广义表:必考内容 
    119 *    广义表的书写,看成一个字符串S
    120 *    下面头尾链表法创建一个广义表 
    121 */ 
    122 using namespace std;
    123 string emp = "()" ;
    124 
    125 void sever(string &str,string &hstr){
    126     //将非空串str分割成两部分,hstr是表头
    127     int n = str.size();
    128     int i = -1;
    129     int k = 0; //k记录尚未配对的“(” 数
    130     char ch;    
    131     do{ //搜索最外层第一个( 
    132         ++i;
    133         ch = str[i];
    134         if(ch == '(') ++k;
    135         else if(ch == ')') --k;
    136     }while(i<n&&(ch != ','||k!=0));
    137      if(i<n){
    138          hstr =str.substr(0,i);
    139          //printf("in
    ");
    140          str = str.substr(i+1,n-i-1);
    141          //printf("out
    ");
    142      }else{
    143          hstr = str.substr(0,str.size());
    144          str.clear();
    145      }
    146 }
    147 
    148 void CreateGList(GList &L,string s){
    149     //采用头尾链表存储结构,创建L
    150     if(s.compare(emp) == 0) L = NULL;
    151     else{
    152         L = (GList)malloc(sizeof(GLNode));
    153         if(!L) exit(0);
    154         if(s.size() == 1){ //单个元素,建立原子节点 
    155             L->tag = ATOM;
    156             L->atom = s[0];
    157         }else{ //表节点 ,表尾 
    158             L->tag = LIST;
    159             GList p,q;
    160             p = L; //p是指向当前子表(表尾节点)的指针 
    161             string sub;
    162             sub = s.substr(1,s.size()-2); //去掉外层括号 
    163             string hsub;
    164             do{ //重复建立n个子表 
    165                 sever(sub,hsub); //sub中分理出表头串hsub ,同时,sub去除了hsub
    166                 CreateGList(p->ptr.hp,hsub);
    167                 q = p; //记录p,下面sub不为空,要再建立一个表尾节点,q记录上一层的p,用以连接q->ptr.tp = q 
    168                 if(!sub.empty()) {
    169                     p = (GList)malloc(sizeof(GLNode));
    170                     if(!p)exit(0);
    171                     p -> tag = LIST;
    172                     q -> ptr.tp = p;
    173                 }//if
    174             }while(!sub.empty());
    175             q -> ptr.tp = NULL;
    176         //    printf("has complete
    ");
    177         }
    178     }
    179 }
    180  
    181 
    182 int main(){
    183 //    string s = "1232342342";
    184 //    if(s.compare("123") == 0){
    185 //        printf("13");
    186 //    }
    187 //    printf("
    ");
    188 //    s = s.substr(1,s.size()-2);
    189 //    for(int i = 0;i<s.size();i++){
    190 //        printf("%c",s[i]);
    191 //    }
    192     
    193     string ss = "(2,3,4,(1,2))";
    194     GList L;
    195     CreateGList(L,ss);
    196     printf("深度:");
    197     printf("%d",GListDepth(L));
    198     return 0;
    199 }
  • 相关阅读:
    这是在CNblogs倒闭前,本blog最后一篇随笔,请各位看官好好珍惜,主题:改变Docker Port 2376从你我做起,有图为证
    娱乐往事,年初捡到1G PAR,平淡的日子泛起波澜(小编,今天你移了多少次了?给一个说法吧,置顶了)
    DOCKER绝对领域从2048到4069?不:25519,数字的飞跃,HTTP/2
    再次聚焦DOCKER MACHINE CODE 2048
    视觉光盘,只有我可以贴全世界唯一,Windows上最高级的DOCKER客户端数字, 夜晚点击一个都没有,值班的小编辛苦了
    视觉光盘,只有我可以贴全世界唯一,你永远截不到的图片(小编请用人性化语言解释移出首页)
    深夜话题boot2docker还有那些隐藏MENU
    Go Goosy Disk Docker Port Provisioners (GDP)
    揭发233的docker/machine
    手动滑稽之golang-vmware-driver广告篇
  • 原文地址:https://www.cnblogs.com/duye/p/8954746.html
Copyright © 2011-2022 走看看