数据结构——串

  • 语言:C语言
  • 软件:Visual Studio 2022
  • 笔记书籍:数据结构——用C语言描述
  • 如有错误,感谢指正。若有侵权请联系博主

 一、串的基本概念

子串:串中任意连续的字符组成的子序列称为该串的子串。

主串:包含子串的串称为主串。即,子串是主串的一部分。

子串在主串中的位置:通常将字符在串中的序号称为该字符在串中的位置。子串在主串中的位置则以子串的第一个字符在主串中的位置来表示。

串相等:当且仅当两个串的值相等时,称这两个串是相等的,即只有当两个串的长度相等,并且每个对应位置的字符都相等时才为串相等。

串的抽象数据类型定义

ADT String{数据对象:D={a(n)|a(n)∈CharacterSet,n=1,2,...,n,n>=0}结构关系:R={<a(n),a(n+1)> | a(n),a(n+1)∈D,i=1,...,n-1,n>=1}基本操作:1、StrAssign(S,chars)操作前提:chars时字符串常量操作结果:生成一个值等于chars的串s。2、StrInsert(S,pos,T)操作前提:串S存在,1<=pos<=StrLength(S)+1。操作结果:在串S的第pos个字符之前插入串T。3、StrDelete(S,pos,len)操作前提:串S存在,1<=pos<=StrLength(S)+1。操作结果:从串S中删除第pos个字符起长度为len的子串。4、StrCopy(S,T)操作前提:串S存在。操作结果:由串T复制的串S。5、StrEmpty(S)操作前提:串S存在。操作结果:若串S为空串,则返回TRUE,否则返回FALSE。6、StrCompare(S,T)操作前提:串S和T存在。操作结果:若S>T,则返回值大于0;如S=T,则返回值0;若S<T,则返回值小于0。7、StrLength(S)操作前提:串S存在。操作结果:返回串S的长度,即串S中的字符个数。8、StrClear(S)操作前提:串S存在。操作结果:将S清为空串。9、StrCat(S,T)操作前提:串S和T存在。操作结果:将串T的值连接在串S的后面。10、SubString(Sub,S,pos,len)操作前提:串S存在,1<=pos<=StrLength(S)且1<=len<=StrLength(S)-pos+1。操作结果:用Sub返回串S的第pos个字符起长度为len的子串。11、StrIndex(S,pos,T)操作前提:串S和T存在,T是非空串,1<=pos<=StrLength(S)。操作结果:若串S中存在和串T相同的子串,则返回它在串S中第pos个字符之后第一个出现的位置;否则返回0。12、StrReplace(S,T,V)操作前提:串S、T和V存在,且T是非空串。操作结果:用V替换串S中出现的所有与T相等的不重叠的子串。13、StrDestroy(S)操作前提:串S存在。操作结果:销毁串S。
}

二、串的存储实现——定长顺序串

定长顺序串是将串设计成一种静态结构类型,串的存储分配是在编译时完成的。与前面所讲的线性表的顺序存储结构类似,可用一组地址连续的存储单元来存储串的字符序列。

1.定长顺序串存储结构

typedef struct {char ch[MAXString];int len;
}SString;

2.StrAssign初始化字符串

int StrAssign(SString *S,const char *chars) {S->len = 0;if (*chars == NULL) return TRUE;if (strlen(chars)>MAXString) return FALSE;while(chars[S->len] != '\0') {S->ch[S->len] = chars[S->len];S->len++;}return TRUE;
}

3.StrInsert在第pos个字符前插入字符串T

int StrInsert(SString* S, int pos, SString T) {if (pos<1 || pos>S->len+1) return FALSE;int i;if (S->len + T.len <= MAXString) {printf("S的长度%d,T的长度%d\n", S->len, T.len);for (i = S->len + T.len - 1; i >= T.len -1 + pos; i--){ S->ch[i] = S->ch[i - T.len];}for (i = 0; i < T.len; i++) S->ch[i - 1 + pos] = T.ch[i];S->len = S->len + T.len;}else if (pos + T.len <= MAXString) {for (i = MAXString; i > T.len + pos; i--) S->ch[i] = S->ch[i - T.len+1];for (i = 0; i < T.len; i++)S->ch[i + pos] = T.ch[i];S->len = MAXString;}else {for (i = 0; i < MAXString - pos; i++) S->ch[i + pos] = T.ch[i];S->len = MAXString;}return TRUE;
}

在进行顺序串的插入时,插入位置pos将串分为俩部分(假设为A、B,长度为LA、LB)及待插入部分(假设C,长度为LC),则串由插入前的AB变为ACB。由于时顺序串,插入会引起元素的移动,可能出现一下三种情况:

  1. 插入后串长(LA+LC+LB)<=MAXString,则将B往后移LC个元素位置,再将C插入。
  2. 插入后串长>MAXSting且pos+LC<MAXSting,则B后移会有部分字符被舍弃。
  3. 插入后串长>MAXSting且pos+LC>MAXSting,则B的全部字符被舍弃(不需要后移),并且C在插入时也有部分字符被舍弃。

4.StrDelete删除S中从pos个字符起长度为len的子串

int StrDelete(SString* S, int pos, int len) {if (pos<1 || pos>(S->len - len + 1)) return FALSE;for (int i = pos + len - 1; i < S->len; i++) S->ch[i-len] = S->ch[i];S->len -= len;return TRUE;
}

5.StrCopy复制字符串

void StrCopy(SString *S, SString T) {		//由后边参数复制的前边参数,即由T复制得Sfor (int i = 0; i < T.len; i++) S->ch[i] = T.ch[i];S->len = T.len;
}

6.StrEmpty判断字符串是否为空

int StrEmpty(SString* S) {if (S->len == 0) return TRUE;return FALSE;
}

7.StrCompare判断俩字符串是否相等

int StrCompare(SString S, SString T) {int i;for (i = 0; i < S.len && i < T.len; i++)if (S.ch[i] != T.ch[i]) return(S.ch[i] - T.ch[i]);return S.len - T.len;
}

8.StrLength获取字符串的长度

int StrLength(SString *S) {return S->len;
}

9.StrClear将串清空为空串

void StrClear(SString* S) {for (int i = 0; i < MAXString; i++) S->ch[i] = NULL;S->len = 0;
}

10.StrCat连接字符串

void StrCat(SString* S, SString T) {     //将T连接在串S后边if (S->len + T.len <= MAXString) {for (int i = 0; i < T.len; i++) S->ch[i + S->len] = T.ch[i];S->len = S->len + T.len;}else {for (int i = 0; S->len + i < MAXString; i++) S->ch[i + S->len] = T.ch[i];S->len = MAXString - 1;}
}

11.SubString用一个串返回第pos个字符起长度为len的子串

int SubString(SString *Sub,SString S,int pos,int len) {if (pos<1 || pos>S.len || 1 > len || len > S.len - pos + 1) return FALSE;for (int i = 0; i < len; i++) Sub->ch[i] = S.ch[((pos - 1) + i)];Sub->len = len;return TRUE;
}

12.StrIndex定位函数

int StrIndex(SString S, int pos, SString T) {int i, j, start;if (T.len == 0) return FALSE;start = pos - 1; i = start; j = 0;while(i<S.len && j < T.len)if (S.ch[i] == T.ch[j]) { i++; j++;}else {start++;i = start; j = 0;}if (j >= T.len) return start+1;else return -1;
}

定位函数:若S中存在和T相同的子串,则返回它在串S中第pos个字符之后第一次出现的位置。

简单模式匹配算法:

从主串S的pos位置起,与模式串T逐位匹配。

  1. 初始化:主串从pos开始,模式串从头开始。
  2. 两串逐位比较:当主串、模式串均未遍历完时,对应字符做比较,若相等则主串、模式串的当前比较位置均往后移;若不等则主串从开始比较位置的下一个开始,模式串从头开始。
  3. 判别:若匹配成功则返回起始位置,若不成功则返回-1。

 13.StrReplace替换字符串

int StrReplace(SString* S, SString T, SString V) {if (0 == StrCompare(*S, T)) return FALSE;int pos = 1,i;while(1) {pos = StrIndex(*S, pos, T);if (S->len + V.len - T.len > MAXString) return FALSE;StrDelete(S,pos,T.len);StrInsert(S, pos, V);if (pos == -1) break;}return TRUE;
}

先比较S和T是否是相等的;再用循环去逐个替换。循环内,先获取需要替换的位置,用字符串定位函数,顺便更新开始查找位置,再判断替换后会不会超出数据的存储范围,再根据替换位置,删除原本数据,再将需要更新的数据写入进去。

14、全部代码加测试

#include <stdio.h>
#include <string.h>
#define MAXString 50
#define TRUE 1
#define FALSE 0typedef struct {char ch[MAXString];int len;
}SString;int StrAssign(SString *S,const char *chars) {S->len = 0;if (*chars == NULL) return TRUE;if (strlen(chars)>MAXString) return FALSE;while(chars[S->len] != '\0') {S->ch[S->len] = chars[S->len];S->len++;}return TRUE;
}int StrInsert(SString* S, int pos, SString T) {if (pos<1 || pos>S->len+1) return FALSE;int i;if (S->len + T.len <= MAXString) {printf("S的长度%d,T的长度%d\n", S->len, T.len);for (i = S->len + T.len - 1; i >= T.len -1 + pos; i--){ S->ch[i] = S->ch[i - T.len];}for (i = 0; i < T.len; i++) S->ch[i - 1 + pos] = T.ch[i];S->len = S->len + T.len;}else if (pos + T.len <= MAXString) {for (i = MAXString; i > T.len + pos; i--) S->ch[i] = S->ch[i - T.len+1];for (i = 0; i < T.len; i++)S->ch[i + pos] = T.ch[i];S->len = MAXString;}else {for (i = 0; i < MAXString - pos; i++) S->ch[i + pos] = T.ch[i];S->len = MAXString;}return TRUE;
}int StrDelete(SString* S, int pos, int len) {if (pos<1 || pos>(S->len - len + 1)) return FALSE;for (int i = pos + len - 1; i < S->len; i++) S->ch[i-len] = S->ch[i];S->len -= len;return TRUE;
}void StrCopy(SString *S, SString T) {		//由后边参数复制的前边参数for (int i = 0; i < T.len; i++) S->ch[i] = T.ch[i];S->len = T.len;
}int StrEmpty(SString* S) {if (S->len == 0) return TRUE;return FALSE;
}int StrCompare(SString S, SString T) {int i;for (i = 0; i < S.len && i < T.len; i++)if (S.ch[i] != T.ch[i]) return(S.ch[i] - T.ch[i]);return S.len - T.len;
}int StrLength(SString *S) {return S->len;
}void StrClear(SString* S) {for (int i = 0; i < MAXString; i++) S->ch[i] = NULL;S->len = 0;
}void StrCat(SString* S, SString T) {if (S->len + T.len <= MAXString) {for (int i = 0; i < T.len; i++) S->ch[i + S->len] = T.ch[i];S->len = S->len + T.len;}else {for (int i = 0; S->len + i < MAXString; i++) S->ch[i + S->len] = T.ch[i];S->len = MAXString - 1;}
}int SubString(SString *Sub,SString S,int pos,int len) {if (pos<1 || pos>S.len || 1 > len || len > S.len - pos + 1) return FALSE;for (int i = 0; i < len; i++) Sub->ch[i] = S.ch[((pos - 1) + i)];Sub->len = len;return TRUE;
}int StrIndex(SString S, int pos, SString T) {int i, j, start;if (T.len == 0) return FALSE;start = pos - 1; i = start; j = 0;while(i<S.len && j < T.len)if (S.ch[i] == T.ch[j]) { i++; j++;}else {start++;i = start; j = 0;}if (j >= T.len) return start+1;else return -1;
}int StrReplace(SString* S, SString T, SString V) {if (0 == StrCompare(*S, T)) return FALSE;int pos = 1,i;while(1) {pos = StrIndex(*S, pos, T);if (S->len + V.len - T.len > MAXString) return FALSE;StrDelete(S,pos,T.len);StrInsert(S, pos, V);if (pos == -1) break;}return TRUE;
}void Print_SString(SString S) {for (int i = 0; i < S.len; i++) printf("%c ", S.ch[i]);printf("\n");
}void main() {SString s, t, v, q, * S, * T, * V,* Q;S = &s; T = &t; V = &v; Q = &q;printf("——————————初始化串,分别生成串S,T,V————————————\n");StrAssign(S, "abcdabcd*fghijbcduuhds");StrAssign(T, "abc");StrAssign(V, "**987654**");printf("串S为:");Print_SString(s);printf("\n串T为:");Print_SString(t);printf("\n串V为:");Print_SString(v);printf("\n————————————在S串中第三个字符前插入串V————————————\n");StrInsert(S,3,*V);printf("插入后的S为:");Print_SString(*S);printf("\n————————————用串T返回S串中第5起8长的子串————————————\n");SubString(T,*S,5,8);printf("\n串T为:");Print_SString(t);printf("\n————————————删除从第pos个字符起长度为len的子串————————————\n");printf("删除是否成功(1成功,0不成功):%d", StrDelete(S, 30, 5));printf("\n删除是否成功(1成功,0不成功):%d", StrDelete(S, 20, 15));printf("\n删除是否成功(1成功,0不成功):%d", StrDelete(S, -1, 5));printf("\n删除是否成功(1成功,0不成功):%d", StrDelete(S, 1, 2));printf("\n删除后的S为:");Print_SString(*S);printf("\n————————————由串T复制得V————————————\n");printf("串V复制前:");Print_SString(v);StrCopy(V,*T);printf("串V复制后:");Print_SString(v);printf("\n————————————将串V的值连接在串T后面————————————\n");printf("串T连接前:");Print_SString(t);StrCat(T,*V);printf("串T连接后:");Print_SString(t);printf("\n————————————判断串是否为空串,以及清空串V————————————\n");printf("串V清空前,空为1,非空为0:%d\n",StrEmpty(V));StrClear(V);printf("串V清空后,空为1,非空为0:%d\n", StrEmpty(V));int i, j, k;printf("\n———————————字符串之间的比较————————————\n");StrAssign(Q, "c");printf("串S为:");Print_SString(s);printf("\n串T为:");Print_SString(t);printf("\n串Q为:");Print_SString(q);printf("S与Q比较,从1开始:%d;S与Q比较,从16开始:%d;T与Q比较:%d", StrIndex(s, 1, q), StrIndex(s,6, q), StrIndex(v, 1, t));printf("\n———————————字符串替换————————————\n");StrAssign(V, "####");printf("串S替换前为:");Print_SString(s);StrReplace(S,*Q,*V);printf("串S替换后为:");Print_SString(s);
}

 15.运行结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/51359.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

做一个能和你互动玩耍的智能机器人之三

内容节选自英特尔的开源项目openbot的body目录下diy下的readme&#xff0c;这是一个组装和连线方式的说明文档&#xff0c;接线需要配合firmware固件使用&#xff0c;固件代码的接线柱是对应的。 body目录内部十分丰富&#xff0c;主要介绍了这个项目的背景和硬件以及如何让他…

【SQL 新手教程 4/20】关系模型 --索引

&#x1f497; 关系数据库建立在关系模型上⭐ 关系模型本质上就是若干个存储数据的二维表 记录 (Record)&#xff1a; 表的每一行称为记录&#xff08;Record&#xff09;&#xff0c;记录是一个逻辑意义上的数据 字段 (Column)&#xff1a;表的每一列称为字段&#xff08;Colu…

iOS 评论弹窗手势问题

基本原理 给slidePopupView添加一个滑动手势 并设置代理 我们在 shouldReceiveTouch 代理方法中 通过 touch.view 判断 是否是滑动tableView, 如果 touch.view 是tableView &#xff0c; isDragScrollView 就是YES, 否则就是NO 并且要 shouldRecognizeSimultaneouslyWithGestu…

Unity发布安卓解决报错: You will no longer be able to disable R8

Unity发布安卓解决报错&#xff1a; You will no longer be able to disable R8 问题描述1 版本&#xff1a;2 问题描述&#xff1a;3 分析&#xff1a; 解决方案1 升级工程2 选择安卓版本12L3 直接打包 问题描述 1 版本&#xff1a; unity 2021 2 问题描述&#xff1a; da…

go run command

文章目录 1.简介2.格式3.示例4.注意事项5.常见用途参考文献 1.简介 编译并运行 Go 程序。 2.格式 go run [build flags] [-exec xprog] package [arguments...]run 编译并运行指定的 main 包。 通常&#xff0c;main 包被指定为来自单个目录的 .go 源文件列表&#xff0c;但…

echarts实现在市级行政区点击县级行政区,显示单个县级行政区地图数据

因需兼容ie&#xff0c;此处所有变量声明都用var。如无需支持&#xff0c;可另做let修改。 这里以常州市为例,我们可以去阿里云提供的地理工具去截取地图json数据DataV.GeoAtlas地理小工具系列 点击所选区域&#xff0c;右侧会对应显示json数据&#xff0c;再次点击右侧红框内…

MySQL 索引相关基本概念

文章目录 前言一. B Tree 索引1. 概念2. 聚集索引/聚簇索引3. 辅助索引/二级索引4. 回表5. 联合索引/复合索引6. 覆盖索引 二. 哈希索引三. 全文索引 前言 InnoDB存储引擎支持以下几种常见索引&#xff1a;BTree索引&#xff0c;哈希索引&#xff0c;全文索引 一. B Tree 索引…

java如何实现接口之间的继承

java如果要实现接口之间的继承需要用到语句 interface 接口1 extends 接口2&#xff0c;接口3 一个接口可以继承多个接口 示例代码如下 interface Animal03{public String name"牧羊犬";public void info(); } interface Color{public void black(); } interface…

2024巴黎奥运会竟然用AI做这些?

人工智能将成为 2024 年巴黎奥运会的焦点&#xff0c;组织者于四月制定了《奥运会人工智能议程》&#xff0c;这是一个涵盖人工智能对奥运会未来影响的框架。 该议程体现了国际奥委会及其主要合作伙伴的承诺&#xff0c;确保在奥运会上使用人工智能来促进团结、提高可持续性并加…

从零到一使用 Ollama、Dify 和 Docker 构建 Llama 3.1 模型服务

本篇文章聊聊&#xff0c;如何使用 Ollama、Dify 和 Docker 来完成本地 Llama 3.1 模型服务的搭建。 如果你需要将 Ollama 官方不支持的模型运行起来&#xff0c;或者将新版本 llama.cpp 转换的模型运行起来&#xff0c;并且想更轻松的使用 Dify 构建 AI 应用&#xff0c;那么…

网络传输层——UDP与TCP

前言&#xff1a; 1.国际网络体系结构&#xff1a; OSI模型: open system interconnect 理论模型 1977 国际标准化组织 各种不同体系结构的计算机能在世界范围内互联成网。 应用层:要传输的数据信息&#xff0c;如文件传输&#xff0c;电子邮件等…

数据结构:队列(顺序存储和链式存储)

文章目录 1. 队列的概念和结构2. 队列的链式存储实现2.1 初始化2.2 判断队列是否为空2.3 入队列2.4 出队列2.5 取队头数据2.6 取队尾数据2.7 队列有效数据的个数2.8 打印队列数据2.9 销毁2.10 源代码 3. 队列的顺序存储实现(循环队列)3.1 初始化3.2 判断队列是否为空3.3 判断队…

【数据结构之C语言实现动态顺序表】

引 入: 在讲顺序表之前得先了解线性表是什么&#xff1f; 线性表是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表&#xff0c;链表&#xff0c;栈&#xff0c;队列&#xff0c;字符串…… 线性表…

Meta 发布地表最大、最强大模型 Llama 3.1

最近这一两周看到不少互联网公司都已经开始秋招提前批了。不同以往的是&#xff0c;当前职场环境已不再是那个双向奔赴时代了。求职者在变多&#xff0c;HC 在变少&#xff0c;岗位要求还更高了。 最近&#xff0c;我们又陆续整理了很多大厂的面试题&#xff0c;帮助一些球友解…

【iOS】暑期第一周——ZARA app仿写

目录 前言无限轮播图分栏控件和滚动视图自定义cell遇到的问题调整图标大小单元格附件视图设置 总结 前言 暑假学习的第一周任务是对ZARA app进行仿写&#xff0c;充分运用之前学习的Objective-C语言和UI控件。我在编写demo的过程中遇到了一些问题&#xff0c;特写该博客作为学习…

【Go】探索 Go 语言的内建函数 make

山水间歌声回荡 回荡思念的滚烫 去年的家书两行 读来又热了眼眶 云水边静沐暖阳 烟波里久违的故乡 别来无恙 你在心上 &#x1f3b5; 张靓颖/张杰《燕归巢》 在 Go 语言中&#xff0c;make 是一个非常强大的内建函数&#xff0c;用于创建和初始化特定类型…

LLM与搜索推荐

重磅推荐专栏: 《大模型AIGC》 《课程大纲》 《知识星球》 本专栏致力于探索和讨论当今最前沿的技术趋势和应用领域,包括但不限于ChatGPT和Stable Diffusion等。我们将深入研究大型模型的开发和应用,以及与之相关的人工智能生成内容(AIGC)技术。通过深入的技术解析和实践经…

VScode连接服务器免密登录

1、生成 SSH 密钥对 打开终端并输入以下命令生成 SSH 密钥对&#xff1a; 直接搜索 cmd&#xff0c;然后输入&#xff1a; ssh-keygen -t rsa -b 4096 一直回车就好了 这时公钥存储在/Users/你的用户名/.ssh/id_rsa.pub文件里&#xff0c;私钥存储在/Users/你的用户名/.ss…

B Tree和B+ Tree的区别

1. 叶子节点的存储 2. 查询效率 3. 范围查询 4. 内存使用 5. 插入和删除 6. 应用场景 总结 B树&#xff08;B-Tree&#xff09;和B树&#xff08;B Tree&#xff09;都是广泛应用于数据库和文件系统中的自平衡树数据结 构&#xff0c;主要用于存储和检索大量数据。虽然它…

简单的数据结构:栈

1.栈的基本概念 1.1栈的定义 栈是一种线性表&#xff0c;只能在一端进行数据的插入或删除&#xff0c;可以用数组或链表来实现&#xff0c;这里以数组为例进行说明 栈顶 &#xff1a;数据出入的那一端&#xff0c;通常用Top表示 栈底 :相对于栈顶的另一端&#xff0c;也是固…