当前位置:   article > 正文

串的数据结构表——顺序串与链式串(C语言版)_c语言链式串的比较

c语言链式串的比较

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #define MAXSIZE 100
  4. //串的顺序存储
  5. typedef struct st
  6. {
  7. char *ch; //串存放的起始地址,串中第i个字符存储在ch[i-1]中
  8. int length; //串的长度
  9. int strsize; //分配的存储空间的大小,如果不足,在通过realloc()分配增加空间
  10. }string;
  11. //串的初始化操作
  12. string CreateNullString()
  13. {
  14. string s;
  15. s.length = 0;
  16. s.ch = (char*)malloc(MAXSIZE *sizeof(char));
  17. s.strsize = MAXSIZE;
  18. return s;
  19. }
  20. //判断空串
  21. int isEmpty(string s)
  22. {
  23. if (s.length == 0)
  24. return 1;
  25. else
  26. return 0;
  27. }
  28. //赋值操作
  29. void StringAssign(string *s1, char s2[])
  30. {
  31. int i = 0;
  32. while (s2[i] != '\0') // '\0' 是字符串的结束符,任何字符串之后都会自动加上'\0'
  33. i++; //计算s2的长度
  34. if (i>s1->strsize)
  35. {
  36. //所赋值的字符数组超过字符串的默认容量,则增加存储空间
  37. s1->ch = (char*)malloc(i*sizeof(char));
  38. s1->strsize = i;
  39. }
  40. s1->length = i;
  41. for (i = 0; i<s1->length; i++)
  42. s1->ch[i] = s2[i]; //从第一个字符开始逐个字符赋值
  43. }
  44. //串拷贝操作
  45. void StringCopy(string *s1, string s2)
  46. {
  47. if (s1->strsize<s2.length)
  48. {
  49. //realloc则对malloc申请的内存进行大小的调整.
  50. s1->ch = (char*)realloc(s1->ch, s2.length*sizeof(char));
  51. s1->strsize = s2.length;
  52. }
  53. s1->length = s2.length;
  54. int i;
  55. for (i = 0; i<s1->length; i++)
  56. s1->ch[i] = s2.ch[i];
  57. }
  58. //求串的长度
  59. int StringLength(string s)
  60. {
  61. return s.length;
  62. }
  63. //串的连接操作
  64. void concat(string *s, string s1, string s2)
  65. {
  66. if (s->strsize<s1.length + s2.length)
  67. {
  68. s->ch = (char*)realloc(s->ch, (s1.length + s2.length)*sizeof(char));
  69. s->strsize = s1.length + s2.length;
  70. }
  71. s->length = s1.length + s2.length; //两串连接
  72. int i;
  73. for (i = 0; i<s1.length; i++) //将s1复制到s中
  74. s->ch[i] = s1.ch[i];
  75. for (; i<s->length; i++)
  76. s->ch[i] = s2.ch[i - s1.length]; //将s2复制到s中去
  77. }
  78. //取子串操作
  79. int substr(string s, int i, int len, string *t)
  80. {
  81. /*
  82. i表示从字符串s的第i个位置开始截取(索引从1开始)
  83. len表示截取字符串的长度
  84. */
  85. if (i <= 0 || i>s.length || len<0 || len>s.length - i + 1) //参数不合法
  86. return 0;
  87. if (t->length<len) //存储空间不够,继续分配存储空间
  88. {
  89. t->ch = (char*)realloc(t->ch, len*sizeof(char));
  90. t->strsize = len;
  91. }
  92. t->length = len;
  93. int k;
  94. for (k = 0; k<t->length; k++)
  95. t->ch[k] = s.ch[i - 1 + k];
  96. return 1;
  97. }
  98. //插入操作
  99. int insertString(string *s, int i, string t)
  100. {
  101. //在字符串s的第i个位置插入字符串t
  102. if (i <= 0 || i>s->length + 1)
  103. return 0;
  104. if (s->strsize<s->length + t.length) //空间不足
  105. {
  106. s->ch = (char*)realloc(s->ch, (s->length + t.length)*sizeof(char));
  107. s->strsize = s->length + t.length;
  108. }
  109. int k;
  110. for (k = s->length - 1; k >= i - 1; k--) //将s中的后i个字符后移到后面
  111. s->ch[k + t.length] = s->ch[k];//end[][][] ==> e[][][]nd
  112. s->length = s->length + t.length;//s->length=3+3
  113. for (k = 0; k<t.length; k++) //将t的值赋值给s
  114. s->ch[k + i - 1] = t.ch[k];//e[][][]nd==>eaaand
  115. return 1;
  116. }
  117. //删除操作
  118. int deleteString(string *s, int i, int len)
  119. {
  120. //从s的第i个字符开始删除len个字符
  121. if (i <= 0 || i>s->length || len<0 || len>s->length - i + 1) //参数不合法
  122. return 0;
  123. int k;
  124. for (k = i + len - 1; k<s->length; k++) //从s的i+len-1个位置开始将其后的所有字符前移
  125. s->ch[k - len] = s->ch[k];
  126. s->length -= len;
  127. return 1;
  128. }
  129. //输出操作
  130. void print(string s)
  131. {
  132. int i;
  133. for (i = 0; i<s.length; i++)
  134. printf("%c", s.ch[i]);
  135. printf("\n");
  136. }
  137. void main()
  138. {
  139. string s1 = CreateNullString();
  140. string s2 = CreateNullString();
  141. string s3 = CreateNullString();
  142. char ch[MAXSIZE];
  143. printf("请输入主串:\n");
  144. //输入friend
  145. gets(ch);
  146. //赋值操作
  147. StringAssign(&s1, ch);
  148. printf("主串 s1 为:");
  149. print(s1);
  150. //将字符s1拷贝到s2
  151. StringCopy(&s2, s1);
  152. printf("拷贝串操作结果如下,结果如下 s2 :");
  153. print(s2);
  154. printf("删除操作(1——s1.length-3 全删):");
  155. //删除操作
  156. deleteString(&s2, 1, s1.length - 3);
  157. print(s2);
  158. printf("插入操作,插入到s2的第2个位置上,请输入插入的字符串:");
  159. gets(ch);
  160. //赋值操作 把输入的字符放到s3中
  161. StringAssign(&s3, ch);
  162. //进行插入操作,将s3插入到s2的第二个位置上
  163. insertString(&s2, 2, s3);
  164. print(s2);
  165. printf("取子串操作(取s1的子串【2-4】):");
  166. //提取friend 中[2-4]位置元素-rie
  167. substr(s1, 2, 3, &s3);
  168. print(s3);
  169. //s1==>friend s3==>rie
  170. printf("串连接操作【将s1与s3合并】:");
  171. concat(&s1, s1, s2);
  172. print(s1);
  173. system("pause");
  174. }

运行结果:

串的数据结构表——顺序串与链式串

  串的结构类似与线性表,只不过串的数据元素是一个字符,即是由零个或多个字符组成的有限序列。

一、串的顺序存储

  串的顺序存储结构也就是顺序存储,即串中的字符被依次的存在一组连续的存储单元中,可以类比线性表的顺序存储,可以写出其数据结构如下:

typedef struct st { char *ch;       //串存放的起始地址,串中第i个字符存储在ch[i-1]中 int length;     //串的长度 int strsize;    //分配的存储空间的大小,如果不足,在通过realloc()分配增加空间 }string;

   假设现在的字符串是“friend”,其结构可以用如图所示:

  

  现在我们拿到这个数据结构第一步是要初始化一个串,即首先在内存中开辟一段连续的存储空间(大小可以假先预定MAXSIZE个存储空间),初始化其长度length为0,同时制定其串的最大容量是MAXSZIE,如下:

二、串的链式存储

  串的链式存储结构称为串的链式存储,即串中的每一个节点包括两个部分:数据域和指针域,其中数据域用来存放字符,指针域用来存放指向下一个节点的指针。

  由此可得串的链式数据结构如下:

1
2
3
4
5
typedef  struct  node
{
     char  ch;             //字符域
     struct  node *next;   //指针域,存放下一个结点的地址
}node,*linkstr;

 如下所示:

 

 

 其初始化操作主要是开辟头结点,同时让它的下一个指针指向为NULL:

  1. //串的链式存储结构设计与实现
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. //链式串的结构
  5. typedef struct _tag_LinkString
  6. {
  7. char ch;//字符域
  8. struct _tag_LinkString *next;//指针域 存放下一个结点地址域
  9. }LinkString;
  10. //初始化操作:建立一个空串
  11. LinkString* CreatNULLString()
  12. {
  13. LinkString *tmp = NULL;
  14. tmp = (LinkString *)malloc(sizeof(LinkString));
  15. if (NULL == tmp)
  16. {
  17. printf("func err malloc\n");
  18. }
  19. tmp->next = NULL;
  20. return tmp;
  21. }
  22. //判断空串
  23. int iEmpty(LinkString *str)
  24. {
  25. if (str->next == NULL )
  26. {
  27. return 1;
  28. }
  29. else{
  30. return 0;
  31. }
  32. }
  33. //赋值操作
  34. void StringAssignment(LinkString *str,char sourse[])
  35. {
  36. if (NULL == str || NULL == sourse)
  37. {
  38. printf("func err (NULL == str || NULL == sourse)\n");
  39. }
  40. LinkString *tmp1 = NULL, *tmp2 = NULL, *tmp3 = NULL;
  41. tmp3 = str;//tmp3始终指的是尾结点(最后一个非空结点,而不是最后一个NULL结点)
  42. tmp2 = str->next;
  43. int i;
  44. for ( i = 0; sourse[i] != '\0'; i++)
  45. {
  46. //(初始化时只给头结点分配了存储空间或者其他情况),如果需要继续添加数据(其他节点没分配空间)需要继续分配
  47. if (tmp2 != NULL)
  48. {
  49. tmp2->ch = sourse[i];
  50. tmp3 = tmp2;
  51. tmp2 = tmp2->next;
  52. }
  53. else
  54. {
  55. tmp1 = (LinkString *)malloc(sizeof(LinkString));
  56. //添加结点
  57. tmp1->ch = sourse[i];
  58. tmp3->next = tmp1;
  59. tmp3 = tmp1;
  60. }
  61. tmp3->next = NULL;
  62. }
  63. //将s中原来多余的空间释放掉
  64. while (tmp2 != NULL)
  65. {
  66. tmp1 = tmp2->next;
  67. free(tmp2);
  68. tmp2 = tmp1;
  69. }
  70. }
  71. //串的拷贝操作
  72. void StringCopy(LinkString *str, LinkString *other)
  73. {
  74. //1 将other串的值拷贝到str串
  75. LinkString *p, *q, *r, *u;
  76. p = other->next;
  77. q = str->next;
  78. r = str;
  79. while (p!=NULL)
  80. {
  81. //原串原先分配了空间
  82. if (q != NULL)
  83. {
  84. q->ch = p->ch;
  85. r = q;
  86. q = q->next;
  87. }
  88. //若串s原先的空间不够用
  89. else
  90. {
  91. u = (LinkString *)malloc(sizeof(LinkString));
  92. u->ch = p->ch;
  93. r->next = u;
  94. r = u;
  95. }
  96. //p节点后移
  97. p = p->next;
  98. }
  99. //同理,若q的长度过长,可以释放多余的空间
  100. while (q != NULL)
  101. {
  102. p = p->next;
  103. free(q);
  104. q = p;
  105. }
  106. r->next = NULL;
  107. }
  108. //求串的长度
  109. int length(LinkString *s)
  110. {
  111. LinkString *p = NULL;
  112. int n = 0;
  113. p = s->next;
  114. while (p != NULL)
  115. {
  116. n++;
  117. p = p->next;
  118. }
  119. return n;
  120. }
  121. //串的连接操作
  122. void contact(LinkString *s, LinkString *s1, LinkString *s2)
  123. {
  124. LinkString *p, *q, *r, *t;
  125. r = s;
  126. p = s1->next;
  127. q = s->next;
  128. while (p != NULL)
  129. {
  130. if (q != NULL)
  131. {
  132. q->ch = p->ch;
  133. q = q->next;
  134. r = q;
  135. }
  136. else
  137. {
  138. //串s原来没有分配存储空间,需要申请空间
  139. t = (LinkString *)malloc(sizeof(LinkString));
  140. t->ch = p->ch;
  141. r->next = t;
  142. r = t;
  143. }
  144. p = p->next;
  145. }
  146. p = s2->next;
  147. while (p != NULL)
  148. {
  149. if (q != NULL)
  150. {
  151. q->ch = p->ch;
  152. q = q->next;
  153. r = q;
  154. }
  155. else
  156. {
  157. //串s原来没有分配存储空间,需要申请空间
  158. t = (LinkString *)malloc(sizeof(LinkString));
  159. t->ch = p->ch;
  160. r->next = t;
  161. r = t;
  162. }
  163. p = p->next;
  164. }
  165. //将串s的多余的空间清除掉(这个情况只可能发生在while的if循环中)
  166. while (q != NULL)
  167. {
  168. p = q->next;
  169. free(q);
  170. q = p;
  171. }
  172. r->next = NULL;
  173. }
  174. //截取子串
  175. int substr(LinkString *s, int i, int len, LinkString *t)
  176. {
  177. LinkString *p, *q, *r, *u;
  178. if (i <= 0 || i>length(s) || i + len - 1>length(s))
  179. return 0;
  180. //指针指向s的第i-1个位置
  181. int j, k;
  182. for (j = 0, p = s; j<i; j++)
  183. p = p->next;
  184. for (k = 0, r = t, q = t->next; k<len; k++)
  185. {
  186. if (q != NULL)
  187. {
  188. q->ch = p->ch;
  189. r = q;
  190. q = q->next;
  191. }
  192. else
  193. {
  194. u = (LinkString *)malloc(sizeof(LinkString));
  195. u->ch = p->ch;
  196. r->next = u;
  197. r = u;
  198. }
  199. p = p->next;
  200. }
  201. while (q != NULL)
  202. {
  203. p = q->next;
  204. free(q);
  205. q = p;
  206. }
  207. r->next = NULL;
  208. return 1;
  209. }
  210. //插入操作
  211. int insert(LinkString *s, int i, LinkString *t)
  212. {
  213. LinkString *p, *q, *r;
  214. if (i <= 0 || i>length(s) + 1)
  215. return 0;
  216. //指向第i-1个位置
  217. int j;
  218. for (j = 0, p = s; j<i - 1; j++)
  219. p = p->next;
  220. q = t->next;
  221. while (q != NULL)
  222. {
  223. r = (LinkString *)malloc(sizeof(LinkString));
  224. r->ch = q->ch;
  225. r->next = p->next;
  226. p->next = r;
  227. q = q->next;
  228. p = r;
  229. }
  230. return 1;
  231. }
  232. //删除操作
  233. int deleteString(LinkString *s, int i, int len){
  234. LinkString *p, *q;
  235. //防止非法输入
  236. if (i <= 0 || i>length(s) || i + len - 1>length(s))
  237. return 0;
  238. int j;
  239. //将p移动到删除位置i
  240. for (j = 0, p = s; j<i - 1; j++)
  241. p = p->next;
  242. //将i后的位置元素进行删除
  243. for (j = 0; j<len; j++)
  244. {
  245. q = p->next;
  246. p->next = q->next;
  247. free(q);
  248. }
  249. return 1;
  250. }
  251. //打印输出
  252. void print(LinkString *s)
  253. {
  254. LinkString *p = s->next;
  255. while (p != NULL)
  256. {
  257. printf("%c", p->ch);
  258. p = p->next;
  259. }
  260. printf("\n");
  261. }
  262. void main()
  263. {
  264. LinkString *s1 = NULL;
  265. LinkString *s2 = NULL;
  266. LinkString *s3 = NULL;
  267. //1 初始化操作
  268. s1 = CreatNULLString();
  269. s2 = CreatNULLString();
  270. s3 = CreatNULLString();
  271. char str[100];
  272. printf("请输入字符串:\n");
  273. gets(str);
  274. //2 str赋值操作于s1
  275. StringAssignment(s1, str);
  276. printf("串s1:");
  277. print(s1);
  278. printf("串s1的长度为:%d\n", length(s1));
  279. //3 串拷贝操作
  280. StringCopy(s2, s1);
  281. printf("串s2:");
  282. print(s2);
  283. printf("串s2删除操作(第三个位置的三个字符删除 :");
  284. //4 删除操作
  285. deleteString(s2, 3, 3);
  286. print(s2);
  287. printf("串连接操作(s3=s1+s2 ):");
  288. //5 串的连接操作
  289. contact(s3, s1, s2);
  290. print(s3);
  291. printf("插入操作(从s1的第6个位置插入s3):");
  292. //6 串的插入操作
  293. insert(s1, 6, s3);
  294. print(s1);
  295. printf("测试截取子串的功能s2(截取s3的第四个位置长度为4的字符串:");
  296. //7 串的截取操作
  297. substr(s3, 4, 4, s2);
  298. print(s2);
  299. printf("测试字Contact的清除过多存储空间的功能:(将两个较短的字符[两个s2]合并写到s1上去:");
  300. //8 串的连接操作
  301. contact(s1, s2, s2);
  302. print(s1);
  303. system("pause");
  304. }

KMP算法原理:






  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. void prefix_table(char pattern[], int prefix[], int n)
  5. {
  6. prefix[0] = 0;
  7. int len = 0;//比较的长度
  8. int i = 1;
  9. while (i < n)
  10. {
  11. printf("i = %d,len = %d\n",i,len);
  12. if (pattern[i] == pattern[len])
  13. {
  14. len++;
  15. prefix[i] = len;
  16. i++;//往后检测下个
  17. }
  18. else
  19. {
  20. if (len > 0)
  21. {
  22. len = prefix[len -1];//
  23. }
  24. else
  25. {
  26. //这里len = 0
  27. prefix[i] = len;
  28. i++;
  29. }
  30. }
  31. }
  32. }
  33. //将前缀表后移一位,并且在第一位放上-1
  34. void move_prefix_table(int prefix[], int n)
  35. {
  36. int i;
  37. for ( i = n - 1; i > 0; i--)
  38. {
  39. prefix[i] = prefix[i-1];
  40. }
  41. prefix[0] = -1;
  42. }
  43. //KMP搜索
  44. void Kmp_search(char text[], char pattern[])
  45. {
  46. int n = strlen(pattern);
  47. int m = strlen(text);
  48. int *prefix = malloc(sizeof(int) * n);
  49. //调用弄出前缀表
  50. prefix_table(pattern, prefix, n);
  51. //做移位处理
  52. move_prefix_table(prefix, n);
  53. //text[i] ,len(text)=n
  54. //pattern[j] len(pattern)=m
  55. int i = 0, j = 0;
  56. while (i < m)
  57. {
  58. if (j == n -1&&text[i] == pattern[j])
  59. {
  60. printf("Found pattern at %d\n", i - j);
  61. j = prefix[j];
  62. }
  63. if (text[i] == pattern[j])
  64. {
  65. i++;
  66. j++;
  67. }
  68. else
  69. {
  70. j = prefix[j];
  71. if (j == -1)
  72. {
  73. i++;
  74. j++;
  75. }
  76. }
  77. }
  78. }
  79. int main()
  80. {
  81. char pattern[] = "ABABCABAA";
  82. char text[] = "ABABABCABAABCABAAADDDUUU";
  83. Kmp_search(text,pattern);
  84. /*
  85. int prefix[9];
  86. int n = 9;
  87. //调用弄出前缀表
  88. prefix_table(pattern,prefix,n);
  89. //做移位处理
  90. move_prefix_table(prefix,n);
  91. int i;
  92. for ( i = 0; i < n; i++)
  93. {
  94. printf("%d\n",prefix[i]);
  95. }
  96. */
  97. system("pause");
  98. return 0;
  99. }


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

闽ICP备14008679号