数据结构算法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
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 }
三.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 }
四.测试
测试用例是书上的一个例子,其结构图及对应二叉树如下