当前位置:   article > 正文

《数据结构》-链串的表示和实现_t->head

t->head
  1. #include <string.h>
  2. #include <malloc.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #define TRUE 1
  6. #define FALSE 0
  7. #define OK 1
  8. #define ERROR 0
  9. #define INFEASIBLE -1
  10. typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等
  11. typedef int Boolean; // Boolean是布尔类型,其值是TRUEFALSE
  12. char blank = '#'; // 全局变量,用于填补空余
  13. //串的块链存储表示
  14. #define CHUNK_SIZE 4 // 可由用户定义的块大小
  15. typedef struct Chunk
  16. {
  17. char ch[CHUNK_SIZE];
  18. struct Chunk *next;
  19. } Chunk;
  20. typedef struct LString
  21. {
  22. Chunk *head, *tail; // 串的头和尾指针
  23. int curlen; // 串的当前长度
  24. } LString;
  25. //串采用块链存储结构的基本操作(15个)
  26. #define DestroyString ClearString // DestroyString()与ClearString()作用相同
  27. void InitString(LString *T)
  28. { // 初始化(产生空串)字符串T。另加
  29. T->curlen = 0;
  30. T->head = T->tail = NULL;
  31. }
  32. Status StrAssign(LString *T, char *chars)
  33. { // 生成一个其值等于chars的串T(要求chars中不包含填补空余的字符)。成功返回OK,否则返回ERROR
  34. int i, j, k, m;
  35. Chunk *p, *q;
  36. i = strlen(chars); // i为串的长度
  37. if (!i || strchr(chars, blank)) // 串长为0或chars中包含填补空余的字符
  38. return ERROR;
  39. T->curlen = i;
  40. j = i / CHUNK_SIZE; // j为块链的结点数
  41. if (i % CHUNK_SIZE)
  42. j++;
  43. for (k = 0; k < j; k++)
  44. {
  45. p = (Chunk *)malloc(sizeof(Chunk)); // 生成块结点
  46. if (!p) // 生成块结点失败
  47. return ERROR;
  48. for (m = 0; m < CHUNK_SIZE && *chars; m++) // 给块结点的数据域赋值
  49. *(p->ch + m) = *chars++;
  50. if (k == 0) // 第一个链块
  51. {
  52. T->head = q = p; // 头指针指向第一个链块
  53. }
  54. else
  55. {
  56. q->next = p;
  57. q = p;
  58. }
  59. if (!*chars) // 最后一个链块
  60. {
  61. T->tail = q;
  62. q->next = NULL;
  63. for (; m < CHUNK_SIZE; m++) // 用填补空余的字符填满链表
  64. *(q->ch + m) = blank;
  65. }
  66. }
  67. return OK;
  68. }
  69. Status ToChars(LString T, char **chars)
  70. { // 将串T的内容转换为字符串,chars为其头指针。成功返回OK,否则返回ERROR。另加
  71. Chunk *p = T.head; // p指向第1个块结点
  72. int i;
  73. char *q;
  74. *chars = (char *)malloc((T.curlen + 1) * sizeof(char));
  75. if (!(*chars) || !T.curlen) // 生成字符串数组失败或串T长为0
  76. return ERROR;
  77. q = *chars; // q指向chars的第1个字符
  78. while (p) // 块链没结束
  79. {
  80. for (i = 0; i < CHUNK_SIZE; i++)
  81. if (p->ch[i] != blank) // 当前字符不是填补空余的字符
  82. *q++ = (p->ch[i]); // 赋给q所指字符空间
  83. p = p->next;
  84. }
  85. *chars[T.curlen] = 0; // 串结束符
  86. return OK;
  87. }
  88. Status StrCopy(LString *T, LString S)
  89. { // 初始条件:串S存在
  90. // 操作结果:由串S复制得串T,去掉填补空余的字符。成功返回OK,否则返回ERROR
  91. char *c;
  92. Status i;
  93. if (!ToChars(S, &c)) // c为串S的内容
  94. return ERROR;
  95. i = StrAssign(T, c); // 将串S的内容赋给T
  96. free(c); // 释放c的空间
  97. return i;
  98. }
  99. Status StrEmpty(LString S)
  100. { // 初始条件:串S存在。操作结果:若S为空串,则返回TRUE,否则返回FALSE
  101. if (S.curlen) // 非空
  102. return FALSE;
  103. else
  104. return TRUE;
  105. }
  106. int StrCompare(LString S, LString T)
  107. { // 若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0
  108. char *s, *t;
  109. Status i;
  110. if (!ToChars(S, &s)) // s为串S的内容
  111. return ERROR;
  112. if (!ToChars(T, &t)) // t为串T的内容
  113. return ERROR;
  114. i = strcmp(s, t); // 利用C的库函数
  115. free(s); // 释放s,t的空间
  116. free(t);
  117. return i;
  118. }
  119. int StrLength(LString S)
  120. { // 返回S的元素个数,称为串的长度
  121. return S.curlen;
  122. }
  123. void ClearString(LString *S)
  124. { // 初始条件:串S存在。操作结果:将S清为空串
  125. Chunk *p, *q;
  126. p = S->head;
  127. while (p)
  128. {
  129. q = p->next;
  130. free(p);
  131. p = q;
  132. }
  133. S->head = S->tail = NULL;
  134. S->curlen = 0;
  135. }
  136. Status Concat(LString *T, LString S1, LString S2)
  137. { // 用T返回由S1和S2联接而成的新串(中间可能有填补空余的字符)
  138. LString a1, a2;
  139. Status i, j;
  140. InitString(&a1);
  141. InitString(&a2);
  142. i = StrCopy(&a1, S1);
  143. j = StrCopy(&a2, S2);
  144. if (!i || !j) // 至少有1个串拷贝不成功
  145. return ERROR;
  146. T->curlen = S1.curlen + S2.curlen; // 生成串T
  147. T->head = a1.head;
  148. a1.tail->next = a2.head; // a1,a2两串首尾相连
  149. T->tail = a2.tail;
  150. return OK;
  151. }
  152. Status SubString(LString *Sub, LString S, int pos, int len)
  153. { // 用Sub返回串S的第pos个字符起长度为len的子串。
  154. // 其中,1≤pos≤StrLength(S)且0≤len≤StrLength(S)-pos+1
  155. char *b, *c;
  156. Status i;
  157. if (pos < 1 || pos > S.curlen || len < 0 || len > S.curlen - pos + 1) // pos或len值不合法
  158. return ERROR;
  159. if (!ToChars(S, &c)) // c为串S的内容
  160. return ERROR;
  161. b = c + pos - 1; // b指向串c中串Sub内容的首地址
  162. b[len] = 0; // Sub结束处赋0(字符串结束符)
  163. i = StrAssign(Sub, b); // 将串b的内容赋给Sub
  164. free(c);
  165. return i;
  166. }
  167. int Index(LString S, LString T, int pos)
  168. { // T为非空串。若主串S中第pos个字符之后存在与T相等的子串,
  169. // 则返回第一个这样的子串在S中的位置,否则返回0
  170. int i, n, m;
  171. LString sub;
  172. if (pos >= 1 && pos <= StrLength(S)) // pos满足条件
  173. {
  174. n = StrLength(S); // 主串长度
  175. m = StrLength(T); // 串T长度
  176. i = pos;
  177. while (i <= n - m + 1)
  178. {
  179. SubString(&sub, S, i, m); // sub为从S的第i个字符起,长度为m的子串
  180. if (StrCompare(sub, T)) // sub不等于T
  181. ++i;
  182. else
  183. return i;
  184. }
  185. }
  186. return 0;
  187. }
  188. Status StrInsert(LString *S, int pos, LString T)
  189. { // 1≤pos≤StrLength(S)+1。在串S的第pos个字符之前插入串T
  190. char *b, *c;
  191. int i, j;
  192. Status k;
  193. if (pos < 1 || pos > S->curlen + 1) // pos的值超出范围
  194. return ERROR;
  195. if (!ToChars(*S, &c)) // c为串S的内容
  196. return ERROR;
  197. if (!ToChars(T, &b)) // b为串T的内容
  198. return ERROR;
  199. j = (int)strlen(c); // j为串S的最初长度
  200. c = (char *)realloc(c, (j + strlen(b) + 1) * sizeof(char)); // 增加c的存储空间
  201. for (i = j; i >= pos - 1; i--)
  202. c[i + strlen(b)] = c[i]; // 为插入串b腾出空间
  203. for (i = 0; i < (int)strlen(b); i++) // 在串c中插入串b
  204. c[pos + i - 1] = b[i];
  205. InitString(S); // 释放S的原有存储空间
  206. k = StrAssign(S, c); // 由c生成新的串S
  207. free(b);
  208. free(c);
  209. return k;
  210. }
  211. Status StrDelete(LString *S, int pos, int len)
  212. { // 从串S中删除第pos个字符起长度为len的子串
  213. char *c;
  214. int i;
  215. Status k;
  216. if (pos < 1 || pos > S->curlen - len + 1 || len < 0) // pos,len的值超出范围
  217. return ERROR;
  218. if (!ToChars(*S, &c)) // c为串S的内容
  219. return ERROR;
  220. for (i = pos + len - 1; i <= (int)strlen(c); i++)
  221. c[i - len] = c[i]; // c为删除后串S的内容
  222. InitString(S); // 释放S的原有存储空间
  223. k = StrAssign(S, c); // 由c生成新的串S
  224. free(c);
  225. return k;
  226. }
  227. Status Replace(LString *S, LString T, LString V) // 此函数与串的存储结构无关
  228. { // 初始条件:串S,T和V存在,T是非空串
  229. // 操作结果:用V替换主串S中出现的所有与T相等的不重叠的子串
  230. int i = 1; // 从串S的第一个字符起查找串T
  231. if (StrEmpty(T)) // T是空串
  232. return ERROR;
  233. do
  234. {
  235. i = Index(*S, T, i); // 结果i为从上一个i之后找到的子串T的位置
  236. if (i) // 串S中存在串T
  237. {
  238. StrDelete(S, i, StrLength(T)); // 删除该串T
  239. StrInsert(S, i, V); // 在原串T的位置插入串V
  240. i += StrLength(V); // 在插入的串V后面继续查找串T
  241. }
  242. } while (i);
  243. return OK;
  244. }
  245. void StrPrint(LString T)
  246. { // 输出字符串T。另加
  247. int i = 0, j;
  248. Chunk *h;
  249. h = T.head;
  250. while (i < T.curlen)
  251. {
  252. for (j = 0; j < CHUNK_SIZE; j++)
  253. if (*(h->ch + j) != blank) // 不是填补空余的字符
  254. {
  255. printf("%c", *(h->ch + j));
  256. i++;
  257. }
  258. h = h->next;
  259. }
  260. printf("\n");
  261. }

 

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

闽ICP备14008679号