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("空表无表头!\n");
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("空表无表尾!\n");
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\nL是否空?%d(1:是 0:否)\n\n",
365 GListDepth(L), GListEmpty(L));
366 StrAssign(t, p);
367 CreateGList(&L, t); // 创建广义表
368 printf("\n广义表L的长度 = %d\n", GListLength(L));
369 printf("广义表L的深度 = %d \nL是否空?%d(1:是 0:否)\n",
370 GListDepth(L), GListEmpty(L));
371 printf("遍历广义表L:\n");
372 Traverse_GL(L, visit);
373 printf("\n\n复制广义表m = L\n");
374 CopyGList(&m, L);
375 printf("广义表m的长度 = %d\n", GListLength(m));
376 printf("广义表m的深度 = %d\n", GListDepth(m));
377 printf("遍历广义表m:\n");
378 Traverse_GL(m,visit);
379 DestroyGList(&m);
380 m = GetHead(L);
381 printf("\n\nm是L的表头,遍历广义表m:\n");
382 Traverse_GL(m, visit);
383 DestroyGList(&m);
384 m = GetTail(L);
385 printf("\n\nm是L的表尾,遍历广义表m:\n");
386 Traverse_GL(m,visit);
387 InsertFirst_GL(&m, L);
388 printf("\n\n插入L为m的表头,遍历广义表m:\n");
389 Traverse_GL(m,visit);
390 printf("\n\n删除m的表头,遍历广义表m:\n");
391 DestroyGList(&L);
392 DeleteFirst_GL(&m, &L);
393 Traverse_GL(m, visit);
394 printf("\n");
395 DestroyGList(&m);
396 return 0;
397 }