当前位置:   article > 正文

广义表的头尾链表存储表示(2)(第五章 P115 算法5.5,5.6,5.8)_头尾链表存储广义表总是画不对

头尾链表存储广义表总是画不对

 

下图是根据上方程序定义的广义表(a,(b,c,d))的存储结构。它的长度为 2,第 1 个元素为原子 a,第 2 个元素为子表(b,c,d)。

 

完整代码:

下面代码中广义表的书写形式串为HString类型,广义表的书写形式串为SString类型的请转看:https://blog.csdn.net/qq_42185999/article/details/105670079

 

  1. typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
  2. typedef int Boolean; /* Boolean是布尔类型,其值是TRUEFALSE */
  3. #include<malloc.h> /* malloc()等 */
  4. #include<stdio.h> /* EOF(=^Z或F6),NULL */
  5. #include<process.h> /* exit() */
  6. #include<limits.h> //常量INT_MAX和INT_MIN分别表示最大、最小整数
  7. /* 函数结果状态代码 */
  8. #define TRUE 1
  9. #define FALSE 0
  10. #define OK 1
  11. #define ERROR 0
  12. #define INFEASIBLE -1
  13. #define OVERFLOW -2
  14. typedef char AtomType; /* 定义原子类型为字符型 */
  15. /* --------------------------------- 广义表的头尾链表存储表示 --------------------------------*/
  16. typedef enum { ATOM, LIST }ElemTag; /* ATOM==0:原子,LIST==1:子表 */
  17. typedef struct GLNode
  18. {
  19. ElemTag tag; /* 公共部分,用于区分原子结点和表结点 */
  20. union /* 原子结点和表结点的联合部分 */
  21. {
  22. AtomType atom; /* atom是原子结点的值域,AtomType由用户定义 */
  23. struct
  24. {
  25. struct GLNode *hp, *tp;
  26. }ptr; /* ptr是表结点的指针域,prt.hp和ptr.tp分别指向表头和表尾 */
  27. }a;
  28. }*GList, GLNode; /* 广义表类型 */
  29. /* ---------------------------------------------------------------------------------------------*/
  30. /* --------------------------- 广义表的头尾链表存储的基本操作(11个) --------------------------*/
  31. Status InitGList(GList *L)
  32. { /* 创建空的广义表L */
  33. *L = NULL;
  34. return OK;
  35. }
  36. void DestroyGList(GList *L) /* 广义表的头尾链表存储的销毁操作 */
  37. { /* 销毁广义表L */
  38. GList q1, q2;
  39. if (*L)
  40. {
  41. if ((*L)->tag == ATOM)
  42. {
  43. free(*L); /* 删除原子结点 */
  44. *L = NULL;
  45. }
  46. else /* 删除表结点 */
  47. {
  48. q1 = (*L)->a.ptr.hp;
  49. q2 = (*L)->a.ptr.tp;
  50. free(*L);
  51. *L = NULL;
  52. DestroyGList(&q1);
  53. DestroyGList(&q2);
  54. }
  55. }
  56. }
  57. Status CopyGList(GList *T, GList L)
  58. { /* 采用头尾链表存储结构,由广义表L复制得到广义表T。算法5.6 */
  59. if (!L) /* 复制空表 */
  60. *T = NULL;
  61. else
  62. {
  63. *T = (GList)malloc(sizeof(GLNode)); /* 建表结点 */
  64. if (!*T)
  65. exit(OVERFLOW);
  66. (*T)->tag = L->tag;
  67. if (L->tag == ATOM)
  68. (*T)->a.atom = L->a.atom; /* 复制单原子 */
  69. else
  70. {
  71. CopyGList(&((*T)->a.ptr.hp), L->a.ptr.hp);
  72. /* 复制广义表L->ptr.hp的一个副本T->ptr.hp */
  73. CopyGList(&((*T)->a.ptr.tp), L->a.ptr.tp);
  74. /* 复制广义表L->ptr.tp的一个副本T->ptr.tp */
  75. }
  76. }
  77. return OK;
  78. }
  79. int GListLength(GList L)
  80. { /* 返回广义表的长度,即元素个数 */
  81. int len = 0;
  82. if (!L)
  83. return 0;
  84. if (L->tag == ATOM)
  85. return 1;
  86. while (L)
  87. {
  88. L = L->a.ptr.tp;
  89. len++;
  90. }
  91. return len;
  92. }
  93. int GListDepth(GList L)
  94. { /* 采用头尾链表存储结构,求广义表L的深度。算法5.5 */
  95. int max, dep;
  96. GList pp;
  97. if (!L)
  98. return 1; /* 空表深度为1 */
  99. if (L->tag == ATOM)
  100. return 0; /* 原子深度为0 */
  101. for (max = 0, pp = L; pp; pp = pp->a.ptr.tp)
  102. {
  103. dep = GListDepth(pp->a.ptr.hp); /* 求以pp->a.ptr.hp为头指针的子表深度 */
  104. if (dep > max)
  105. max = dep;
  106. }
  107. return max + 1; /* 非空表的深度是各元素的深度的最大值加1 */
  108. }
  109. Status GListEmpty(GList L)
  110. { /* 判定广义表是否为空 */
  111. if (!L)
  112. return TRUE;
  113. else
  114. return FALSE;
  115. }
  116. GList GetHead(GList L)
  117. { /* 取广义表L的头 */
  118. GList h, p;
  119. if (!L)
  120. {
  121. printf("空表无表头!\n");
  122. exit(0);
  123. }
  124. p = L->a.ptr.tp;
  125. L->a.ptr.tp = NULL;
  126. CopyGList(&h, L);
  127. L->a.ptr.tp = p;
  128. return h;
  129. }
  130. GList GetTail(GList L)
  131. { /* 取广义表L的尾 */
  132. GList t;
  133. if (!L)
  134. {
  135. printf("空表无表尾!\n");
  136. exit(0);
  137. }
  138. CopyGList(&t, L->a.ptr.tp);
  139. return t;
  140. }
  141. Status InsertFirst_GL(GList *L, GList e)
  142. { /* 初始条件: 广义表存在 */
  143. /* 操作结果: 插入元素e作为广义表L的第一元素(表头,也可能是子表) */
  144. GList p = (GList)malloc(sizeof(GLNode));
  145. if (!p)
  146. exit(OVERFLOW);
  147. p->tag = LIST;
  148. p->a.ptr.hp = e;
  149. p->a.ptr.tp = *L;
  150. *L = p;
  151. return OK;
  152. }
  153. Status DeleteFirst_GL(GList *L, GList *e)
  154. { /* 初始条件: 广义表L存在 */
  155. /* 操作结果: 删除广义表L的第一元素,并用e返回其值 */
  156. GList p;
  157. *e = (*L)->a.ptr.hp;
  158. p = *L;
  159. *L = (*L)->a.ptr.tp;
  160. free(p);
  161. return OK;
  162. }
  163. void Traverse_GL(GList L, void(*v)(AtomType))
  164. { /* 利用递归算法遍历广义表L */
  165. if (L) /* L不空 */
  166. if (L->tag == ATOM) /* L为单原子 */
  167. v(L->a.atom);
  168. else /* L为广义表 */
  169. {
  170. Traverse_GL(L->a.ptr.hp, v);
  171. Traverse_GL(L->a.ptr.tp, v);
  172. }
  173. }
  174. /* --------------------------------------------------------------------------------------------------*/
  175. /* 广义表的书写形式串为HString类型 */
  176. /* ---------------------------------- 串的堆分配存储 -----------------------------------*/
  177. typedef struct
  178. {
  179. char *ch; /* 若是非空串,则按串长分配存储区,否则chNULL */
  180. int length; /* 串长度 */
  181. }HString;
  182. /* ---------------------------------------------------------------------------------------------*/
  183. /* ------------------------- 需要用到的串采用堆分配存储结构的基本操作 ------------------------*/
  184. Status StrAssign(HString *T, char *chars)
  185. { /* 生成一个其值等于串常量chars的串T */
  186. int i, j;
  187. if ((*T).ch)
  188. free((*T).ch); /* 释放T原有空间 */
  189. i = strlen(chars); /* 求chars的长度i */
  190. if (!i)
  191. { /* chars的长度为0 */
  192. (*T).ch = NULL;
  193. (*T).length = 0;
  194. }
  195. else
  196. { /* chars的长度不为0 */
  197. (*T).ch = (char*)malloc(i * sizeof(char)); /* 分配串空间 */
  198. if (!(*T).ch) /* 分配串空间失败 */
  199. exit(OVERFLOW);
  200. for (j = 0; j < i; j++) /* 拷贝串 */
  201. (*T).ch[j] = chars[j];
  202. (*T).length = i;
  203. }
  204. return OK;
  205. }
  206. Status StrCopy(HString *T, HString S)
  207. { /* 初始条件:串S存在。操作结果: 由串S复制得串T */
  208. int i;
  209. if ((*T).ch)
  210. free((*T).ch); /* 释放T原有空间 */
  211. (*T).ch = (char*)malloc(S.length * sizeof(char)); /* 分配串空间 */
  212. if (!(*T).ch) /* 分配串空间失败 */
  213. exit(OVERFLOW);
  214. for (i = 0; i < S.length; i++) /* 拷贝串 */
  215. (*T).ch[i] = S.ch[i];
  216. (*T).length = S.length;
  217. return OK;
  218. }
  219. Status StrEmpty(HString S)
  220. { /* 初始条件: 串S存在。操作结果: 若S为空串,则返回TRUE,否则返回FALSE */
  221. if (S.length == 0 && S.ch == NULL)
  222. return TRUE;
  223. else
  224. return FALSE;
  225. }
  226. int StrCompare(HString S, HString T)
  227. { /* 若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0 */
  228. int i;
  229. for (i = 0; i < S.length&&i < T.length; ++i)
  230. if (S.ch[i] != T.ch[i])
  231. return S.ch[i] - T.ch[i];
  232. return S.length - T.length;
  233. }
  234. int StrLength(HString S)
  235. { /* 返回S的元素个数,称为串的长度 */
  236. return S.length;
  237. }
  238. Status ClearString(HString *S)
  239. { /* 将S清为空串 */
  240. if ((*S).ch)
  241. {
  242. free((*S).ch);
  243. (*S).ch = NULL;
  244. }
  245. (*S).length = 0;
  246. return OK;
  247. }
  248. Status SubString(HString *Sub, HString S, int pos, int len)
  249. { /* 用Sub返回串S的第pos个字符起长度为len的子串。 */
  250. /* 其中,1≤pos≤StrLength(S)且0≤len≤StrLength(S)-pos+1 */
  251. int i;
  252. if (pos<1 || pos>S.length || len<0 || len>S.length - pos + 1)
  253. return ERROR;
  254. if ((*Sub).ch)
  255. free((*Sub).ch); /* 释放旧空间 */
  256. if (!len) /* 空子串 */
  257. {
  258. (*Sub).ch = NULL;
  259. (*Sub).length = 0;
  260. }
  261. else
  262. { /* 完整子串 */
  263. (*Sub).ch = (char*)malloc(len * sizeof(char));
  264. if (!(*Sub).ch)
  265. exit(OVERFLOW);
  266. for (i = 0; i <= len - 1; i++)
  267. (*Sub).ch[i] = S.ch[pos - 1 + i];
  268. (*Sub).length = len;
  269. }
  270. return OK;
  271. }
  272. void InitString(HString *T)
  273. { /* 初始化(产生空串)字符串T。另加 */
  274. (*T).length = 0;
  275. (*T).ch = NULL;
  276. }
  277. /* -----------------------------------------------------------------------------------------------*/
  278. Status sever(HString *str, HString *hstr)
  279. { /* 将非空串str分割成两部分:hstr为第一个','之前的子串,str为之后的子串 */
  280. int n, i = 1, k = 0; /* k记尚未配对的左括号个数 */
  281. HString ch, c1, c2, c3;
  282. InitString(&ch); /* 初始化HString类型的变量 */
  283. InitString(&c1);
  284. InitString(&c2);
  285. InitString(&c3);
  286. StrAssign(&c1, ",");
  287. StrAssign(&c2, "(");
  288. StrAssign(&c3, ")");
  289. n = StrLength(*str);
  290. do
  291. {
  292. SubString(&ch, *str, i, 1);
  293. if (!StrCompare(ch, c2))
  294. ++k;
  295. else if (!StrCompare(ch, c3))
  296. --k;
  297. ++i;
  298. } while (i <= n && StrCompare(ch, c1) || k != 0);
  299. if (i <= n)
  300. {
  301. StrCopy(&ch, *str);
  302. SubString(hstr, ch, 1, i - 2);
  303. SubString(str, ch, i, n - i + 1);
  304. }
  305. else
  306. {
  307. StrCopy(hstr, *str);
  308. ClearString(str);
  309. }
  310. return OK;
  311. }
  312. Status CreateGList(GList *L, HString S)
  313. { /* 采用头尾链表存储结构,由广义表的书写形式串S创建广义表L。设emp="()" */
  314. HString emp, sub, hsub;
  315. GList p, q;
  316. InitString(&emp);
  317. InitString(&sub);
  318. InitString(&hsub);
  319. StrAssign(&emp, "()");
  320. if (!StrCompare(S, emp)) /* 创建空表 */
  321. *L = NULL;
  322. else
  323. {
  324. *L = (GList)malloc(sizeof(GLNode));
  325. if (!*L) /* 建表结点不成功 */
  326. exit(OVERFLOW);
  327. if (StrLength(S) == 1) /* 创建单原子广义表 */
  328. {
  329. (*L)->tag = ATOM;
  330. (*L)->a.atom = S.ch[0];
  331. }
  332. else
  333. {
  334. (*L)->tag = LIST;
  335. p = *L;
  336. SubString(&sub, S, 2, StrLength(S) - 2); /* 脱外层括号 */
  337. do /* 重复建n个子表 */
  338. {
  339. sever(&sub, &hsub); /* 从sub中分离出表头串hsub */
  340. CreateGList(&p->a.ptr.hp, hsub);
  341. q = p;
  342. if (!StrEmpty(sub)) /* 表尾不空 */
  343. {
  344. p = (GList)malloc(sizeof(GLNode));
  345. if (!p)
  346. exit(OVERFLOW);
  347. p->tag = LIST;
  348. q->a.ptr.tp = p;
  349. }
  350. } while (!StrEmpty(sub));
  351. q->a.ptr.tp = NULL;
  352. }
  353. }
  354. return OK;
  355. }
  356. /* 主程序 */
  357. void visit(AtomType e)
  358. {
  359. printf("%c ", e);
  360. }
  361. void main()
  362. {
  363. char p[80];
  364. GList l, m;
  365. HString t;
  366. InitString(&t);
  367. InitGList(&l);
  368. InitGList(&m);
  369. printf("空广义表l的深度=%d l是否空?%d(1:是 0:否)\n", GListDepth(l), GListEmpty(l));
  370. printf("请输入广义表l(书写形式:空表:(),单原子:a,其它:(a,(b),b)):\n");
  371. gets(p);
  372. StrAssign(&t, p);
  373. CreateGList(&l, t);
  374. printf("广义表l的长度=%d\n", GListLength(l));
  375. printf("广义表l的深度=%d l是否空?%d(1:是 0:否)\n", GListDepth(l), GListEmpty(l));
  376. printf("遍历广义表l:\n");
  377. Traverse_GL(l, visit);
  378. printf("\n复制广义表m=l\n");
  379. CopyGList(&m, l);
  380. printf("广义表m的长度=%d\n", GListLength(m));
  381. printf("广义表m的深度=%d\n", GListDepth(m));
  382. printf("遍历广义表m:\n");
  383. Traverse_GL(m, visit);
  384. DestroyGList(&m);
  385. m = GetHead(l);
  386. printf("\nm是l的表头,遍历广义表m:\n");
  387. Traverse_GL(m, visit);
  388. DestroyGList(&m);
  389. m = GetTail(l);
  390. printf("\nm是l的表尾,遍历广义表m:\n");
  391. Traverse_GL(m, visit);
  392. InsertFirst_GL(&m, l);
  393. printf("\n插入l为m的表头,遍历广义表m:\n");
  394. Traverse_GL(m, visit);
  395. printf("\n删除m的表头,遍历广义表m:\n");
  396. DestroyGList(&l);
  397. DeleteFirst_GL(&m, &l);
  398. Traverse_GL(m, visit);
  399. printf("\n");
  400. DestroyGList(&m);
  401. }

运行结果:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/675150
推荐阅读
相关标签
  

闽ICP备14008679号