Fork me on GitHub

数据结构算法C语言实现(十九)--- 5.5&5.6&5.7广义表

  一.简述

  传说Lisp的基本数据结构就是广义表,广义表也是具有典型递归属性的数据结构,此外,由于建表要处理字符串,用C语言处理起来也是一脸懵逼.....最后自己还想写一个将广义表还原成字符串的函数,一是使其可视化,而是验证算法5.6。花了不少功夫才写出来(强烈建议自己动手写一写),最后是借助树形结构的角度才找到一个不错的解决办法。按照《数据结构编程实验》的分类,数据结构无非线性结构、树状结构、图结构,可以说树是特殊的图(图的最小生成树),线性表示特殊的树。。。。。扯远了!

  二.头文件

  补充版字符串处理头文件

  1 //4_2_part1.h
  2 /**
  3 author:zhaoyu
  4 */
  5 //2016-6-10
  6 //----串的定长顺序存储表示----
  7 #ifndef _4_2_PART1_H_
  8 #define _4_2_PART1_H_
  9 #include "head.h"
 10 #define MAXSTRLEN 255//用户可以在255以内定义最大串长
 11 //这语法还不是很熟悉
 12 typedef unsigned char SString[MAXSTRLEN+1];//0 号单元存放串的长度
 13 int StrLength(SString T)
 14 {
 15     for (int i = 1; i <= MAXSTRLEN; ++i)
 16     {
 17         if ('\0' == T[i])
 18         {
 19             return i-1;
 20         }
 21     }
 22     return MAXSTRLEN;
 23 }
 24 
 25 /**
 26 algorithm 4.2
 27 */
 28 Status Concat(SString &T, SString S1, SString S2)
 29 {
 30     //用 T 返回由 S1 和 S2 连接而成的新串。
 31     //若未截断,则返回 TRUE,否则返回 FALSE
 32     Status uncut;
 33     if (S1[0] + S2[0] < MAXSTRLEN)
 34     {//未截断
 35         int i = 1;
 36         for (i = 1; i <= S1[0]; ++i)
 37         {
 38             T[i] = S1[i];
 39         }
 40         for (i = 1; i <= S2[0]; ++i)
 41         {
 42             T[S1[0]+i] = S2[i];
 43         }
 44         T[0] = S1[0] + S2[0];
 45         uncut = TRUE;
 46     }
 47     else if (S1[0] < MAXSTRLEN)
 48     {
 49         int i = 1;
 50         for (i = 1; i <= S1[0]; i++)
 51         {
 52             T[i] = S1[i];
 53         }
 54         for (i = S1[0]+1; i <= MAXSTRLEN; i++)
 55         {
 56             T[i] = S2[i-S1[0]];
 57         }
 58         T[0] = MAXSTRLEN;
 59         uncut = FALSE;
 60     }
 61     else
 62     {
 63         for (int i = 1; i <= MAXSTRLEN; i++)
 64         {
 65             T[i] = S1[i];
 66         }
 67         T[0] = S1[0] = MAXSTRLEN;
 68         uncut = FALSE;
 69     }
 70     return uncut;
 71 }
 72 /**
 73 algorithm 4.3
 74 */
 75 Status SubString(SString &Sub, SString S, int pos, int len)
 76 {
 77     //用 Sub 返回串 S 的第 pos 个字符起长度为 len 的字串
 78     //其中, 1<= pos <<= SreLength(S) 且 0 <= len <= StrLength(S)-pos+1
 79     if (pos < 1 || pos > S[0] || len < 0 || len > S[0]-pos+1)
 80     {
 81         return ERROR;
 82     }
 83     for (int i = 1; i <= len; i++)
 84     {
 85         Sub[i] = S[i+pos-1];
 86     }
 87     Sub[len+1] = '\0';
 88     Sub[0] = len;
 89     return OK;
 90 }
 91 /**
 92 add for chapter 5 / page 116.117
 93 */
 94 Status StrCompare(SString S, SString T)
 95 {
 96     for (int i = 1; i <= S[0] && i <=T[0]; i++)
 97     {
 98         if (S[i]-T[i] > 0){
 99             return 1;
100         }
101         if (S[i]-T[i] < 0)
102         {
103             return -1;
104         }
105     }
106     if (S[0] == T[0])
107     {
108         return 0;
109     }
110     return S[0]>T[0]?1:-1;
111 }
112 Status StrEmpty(SString S)
113 {
114     if (0 == StrLength(S))
115     {
116         return TRUE;
117     }
118     else
119     {
120         return FALSE;
121     }
122 }
123 Status StrCopy(SString &T, SString S)
124 {//健壮性并不够
125     for (int i = 0; i <= S[0]+1; i++)
126     {
127         T[i] = S[i];
128     }
129     return OK;
130 }
131 Status ClearString(SString S)
132 {
133     S[0] = 0;
134     S[1] = '\0';
135     return OK;
136 }
137 void PrintSString(SString T)
138 {
139     //if(T[])
140     for (int i = 1; i <= T[0]; ++i)
141     {
142         printf("%c", *(T+i));
143     }
144     printf("\n");
145 }
146 #endif
4_2_part1.h
  1 //5_5.h
  2 /**
  3 author:zhaoyu
  4 date;2016-6-16
  5 */
  6 //----广义表的头尾链表存储表示----
  7 #include "4_2_part1.h"
  8 #define AtomType char
  9 typedef enum {ATOM, LIST} ElemTag;//ATOM==0:原子,LIST==1子表
 10 typedef struct GLNode
 11 {
 12     ElemTag tag;//公共部分,用于区分原子结点和表节点
 13     union{//原子结点和表节点的公共部分
 14         AtomType atom;//atom 是原子结点的值域,AtomType由用户定义
 15         struct {struct GLNode *hp, *tp;}ptr;//ptr 是表结点
 16         //的指针域,ptr.hp 和 ptr.tp 分别指向表头和表尾
 17     };
 18 }*GList;//广义表类型
 19 /**
 20 algorithm 5.5
 21 */
 22 int GListDepth(GList L)
 23 {//采用头尾链表存储结构,求广义表 L 深度
 24     if (!L)
 25     {
 26         return 1;//空表深度为 1
 27     }
 28     if (L->tag == ATOM)
 29     {
 30         return 0;//原子深度为 0
 31     }
 32     int MAX = 0;
 33     for (GList pp = L; pp; pp = pp->ptr.tp)
 34     {
 35         int t = GListDepth(pp->ptr.hp);//求以 ptr.hp 为头指针的子表深度
 36         MAX = MAX>t?MAX:t;
 37     }
 38     return MAX+1;
 39 }
 40 /**
 41 algorithm 5.8
 42 */
 43 Status sever(SString &str, SString &hstr)
 44 {//将非空串 str 分割成两部分:hsub为第一个','之前的字串,str 为之后的子串
 45     int n = StrLength(str);
 46     int i = 0, k = 0;//k 记尚未配对的左括号的个数
 47     char ch;
 48     SString CH;
 49     do{
 50         ++i;
 51         SubString(CH, str, i, 1);
 52         ch = CH[1];
 53         if ('(' == ch)
 54         {
 55             ++k;
 56         }
 57         else if (')' == ch){
 58             --k;
 59         }
 60     }while (i < n && (',' != ch || 0 != k));
 61     if (i < n)
 62     {
 63         SubString(hstr, str, 1, i-1);
 64         SubString(str, str, i+1, n-i);
 65     }
 66     else
 67     {
 68         StrCopy(hstr, str);
 69         ClearString(str);
 70     }
 71 }
 72 
 73 /**
 74 algorithm 5.7
 75 */
 76 Status CreateGList(GList &L, SString S)
 77 {//采用头尾链表存储结构,由广义表的书写形式串 S 创建广义表 L,设emp="()"
 78     GList q = NULL, p = NULL;
 79     SString emp = { 2, '(', ')', '\0'};
 80     SString sub, hsub;
 81     if ( 0 == StrCompare(S, emp))
 82     {//创建空表
 83         L = NULL;
 84     }
 85     else
 86     {
 87         if (!(L = (GList)malloc(sizeof(GLNode))))
 88         {
 89             exit(OVERFLOW);//建表结点
 90         }
 91         if (1 == StrLength(S))
 92         {//创建单原子广义表
 93             L->tag = ATOM;
 94             L->atom = S[1];
 95         }
 96         else
 97         {
 98             L->tag = LIST;
 99             p = L;
100             SubString(sub, S, 2, StrLength(S)-2);
101             do{//重复建 n 个子表
102                 sever(sub, hsub);//从 sub 中分离出表头串 hsub
103                 CreateGList(p->ptr.hp, hsub);
104                 q = p;
105                 if (!StrEmpty(sub))
106                 {//表尾不空
107                     if (!(p = (GList)malloc(sizeof(GLNode))))
108                     {
109                         exit(OVERFLOW);
110                     }
111                     p->tag = LIST;
112                     q->ptr.tp = p;
113                 }//if
114             }while (!StrEmpty(sub));
115             q->ptr.tp = NULL;
116         }//else
117     }
118 }
119 /**
120 algorithm 5.6
121 */
122 Status CopyGList(GList &T, GList L)
123 {//采用头尾链表存储结构,由广义表 L 复制得到广义表 T
124     if (!L)
125     {
126         T = NULL;
127     }
128     else
129     {
130         if (!(T = (GList)malloc(sizeof(GLNode))))
131         {
132             exit(OVERFLOW);
133         }
134         T->tag = L->tag;
135         if (ATOM == L->tag)
136         {
137             T->atom = L->atom;
138         }
139         else
140         {
141             CopyGList(T->ptr.hp, L->ptr.hp);
142             CopyGList(T->ptr.tp, L->ptr.tp);
143         }
144     }
145     return OK;
146 }
147 
148 /**
149 my code
150 */
151 int cnt = 0;
152 void PrintGList(GList L)
153 {
154     if (NULL == L)
155     {
156         printf("()");
157     }
158     else
159     {
160         if (ATOM == L->tag)
161         {
162             printf("%c", L->atom);
163         }
164         else
165         {
166             if (NULL == L->ptr.hp)
167             {
168                 printf("(");
169             }
170             if (NULL != L->ptr.hp && LIST == L->ptr.hp->tag)
171             {
172                 printf("(");
173             }
174             PrintGList(L->ptr.hp);        
175             if (NULL != L->ptr.tp && LIST == L->ptr.tp->tag)
176             {
177                 printf(",");
178             }
179             if (NULL == L->ptr.tp)
180             {
181                 printf(")");
182             }
183             else
184             {
185                 PrintGList(L->ptr.tp);
186             }
187             
188             
189         }
190     }
191 }
5_5.h

  三.CPP文件

 1 #include "5_5.h"
 2 int main(int argc, char const *argv[])
 3 {
 4 //    freopen("out.txt", "w", stdout);
 5     //test function sever
 6 
 7     SString s, t;
 8     scanf("%s", s+1);
 9     s[0] = StrLength(s);
10     sever(s, t);
11     printf("t:%s\n", t+1);
12     printf("s:%s\n", s+1);
13 
14     GList L = NULL, T = NULL;
15     SString S;
16     scanf("%s", S+1);
17     S[0] = StrLength(S);
18     printf("len: %d\n", S[0]);
19     CreateGList(L, S);
20     printf("\nL--Depth\t%d\n", GListDepth(L));
21     CopyGList(T, L);
22     printf("\nT--Depth\t%d\n", GListDepth(T));
23     printf("T:\t");
24     PrintGList(T);
25     printf("\n");
26     return 0;
27 }
5_5.cpp

  四.测试

  

  测试用例是书上的一个例子,其结构图及对应二叉树如下

  

  

posted @ 2016-06-17 23:26  赵裕(vimerzhao)  阅读(475)  评论(0编辑  收藏  举报