数据结构算法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

  四.测试

  

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

  

  

时间: 2024-12-08 22:24:11

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

数据结构(C语言版)-第4章 串、数组和广义表

补充:C语言中常用的串运算 调用标准库函数 #include<string.h> 串比较,strcmp(char s1,char s2) 串复制,strcpy(char to,char from)串连接,strcat(char to,char from) 求串长,strlen(char s) 4.1  串 串(String)----零个或多个字符组成的有限序列 串的存储结构:顺序存储.链式存储 顺序存储表示 typedef struct{ char *ch; //若串非空,则按串长分配存储区,

数据结构算法C语言实现(十)--- 3.3栈与递归的实现

一.简介 汉诺塔问题是递归的一个典型例子,而且书上的讲解很详细,对理解C语言函数及函数传参的工作机制很有帮助,值得一看.而且,递归在我看来和分治.DP.贪心等一样是十分优美的思想,值得学习!!! 二.CPP文件 1 //3_3.cpp 2 /** 3 author:zhaoyu 4 email:[email protected] 5 date:2016-6-8 6 note:realize my textbook <<数据结构(C语言版)>> 7 */ 8 //Page 54 9

数据结构算法C语言实现(二十)--- 6.3.1遍历二叉树

一.简述 二叉树的遍历主要是先序.中序.后序及对应的递归和非递归算法,共3x2=6种,其中后序非递归在实现上稍复杂一些.二叉树的遍历是理解和学习递归及体会栈的工作原理的绝佳工具! 此外,非递归所用的栈及相关操作是第三章实现的,但数据类型做了更改. 二.头文件 1 //3_1.h 2 /** 3 author:zhaoyu 4 email:[email protected] 5 date:2016-6-7 6 note:realize my textbook <<数据结构(C语言版)>&g

数据结构算法C语言实现(十二)--- 3.4循环队列&amp;队列的顺序表示和实现

一.简述 空队列的处理方法:1.另设一个标志位以区别队列是空还是满:2.少用一个元素空间,约定以队列头指针在队尾指针下一位置上作为队列呈满的状态的标志. 二.头文件 1 //3_4_part1.h 2 /** 3 author:zhaoyu 4 email:[email protected] 5 date:2016-6-9 6 note:realize my textbook <<数据结构(C语言版)>> 7 */ 8 //Page 64 9 #include <cstdio

数据结构算法C语言实现(八)--- 3.2栈的应用举例:迷宫求解与表达式求值

一.简介 迷宫求解:类似图的DFS.具体的算法思路可以参考书上的50.51页,不过书上只说了粗略的算法,实现起来还是有很多细节需要注意.大多数只是给了个抽象的名字,甚至参数类型,返回值也没说的很清楚,所以很多需要自己揣摩.这也体现了算法和程序设计语言的特点,算法更侧重本质的描述,而任何编程语言都要照顾到实现的细节以及数据类型等语法方面的需求. 表达式求值: [编码中....] 二.头文件 迷宫求解: 1 //3_2_maze.h 2 /** 3 author:zhaoyu 4 email:[em

数据结构算法C语言实现(二)---2.3线性表的链式表示和实现之单链表

一.简述 [暂无] 二.头文件 1 #ifndef _2_3_part1_H_ 2 #define _2_3_part1_H_ 3 //2_3_part1.h 4 /** 5 author:zhaoyu 6 email:[email protected] 7 date:2016-6-4 8 note:realize my textbook <<数据结构(C语言版)>> 9 */ 10 //----线性表的单链表存储结构---- 11 /** 12 My Code 13 to mak

数据结构算法C语言实现(六)---2.4一元多项式的表示及相加

一.简述 利用链表表示稀疏多项式,并基于之前的一些操作(编程实现上还是有所不同的)组合新的操作实现一元多项式的表示及相加. 二.ADT 1 抽象数据类型一元多项式的定义 2 ADT Polyomail{ 3 数据对象:D = {a[i]|a[i]属于TermSet, i = 1,2,3...,m,m>=0 4 TermSet中每个元素包含一个表示系数的实数和表示指数的整数} 5 数据关系 6 基本操作: 7 CreatPolyn(&P, m) 8 操作结果:输入 m 项的系数和指数,建立一元

数据结构算法C语言实现(七)--- 3.1 的线性实现及应用举例

一.简述 栈,LIFO.是操作受限的线性表,和线性表一样有两种存储表示方法.下面以顺序存储为例,实现. 二.ADT 暂无. 三.头文件 1 //3_1.h 2 /** 3 author:zhaoyu 4 email:[email protected] 5 date:2016-6-7 6 note:realize my textbook <<数据结构(C语言版)>> 7 */ 8 //Page 46 9 10 #ifndef _3_1_H_ 11 #define _3_1_H_ 12

数据结构算法C语言实现(十一)--- 3.4队列的链式表示和实现

一.简介 FIFO. 二.头文件 1 //3_4_part1.h 2 /** 3 author:zhaoyu 4 email:[email protected] 5 date:2016-6-9 6 note:realize my textbook <<数据结构(C语言版)>> 7 */ 8 //Page 61 9 #include <cstdio> 10 #include "head.h" 11 #define QElemType int 12 //