当前位置:   article > 正文

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

将串t的值赋值给s,覆盖s原来的值

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

一、串的顺序存储

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

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

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

  

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

  1. //串的初始化操作
  2. string CreateNullString()
  3. {
  4. string s;
  5. s.length=0;
  6. s.ch=(char*)malloc(MAXSIZE *sizeof(char));
  7. s.strsize=MAXSIZE;
  8. return s;
  9. }

 初始化完成之后,我们可以类比顺序表,对串完成一系列操作,如串拷贝、取子串、串赋值等,

 程序示例如下:

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

  结果如下:

 


 

二、串的链式存储

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

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

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

 如下所示:

 

 

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

  1. //初始化操作
  2. linkstr CreateNullString()
  3. {
  4. linkstr s;
  5. s=(linkstr)malloc(sizeof(node));
  6. if(s!=NULL)
  7. s->next=NULL;
  8. return s;
  9. }

由此,完整的案例如下:

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

  结果如图:

 

转载于:https://www.cnblogs.com/helloworldcode/p/6978746.html

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

闽ICP备14008679号