数据结构——串

  • 语言: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…

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 索引…

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;特写该博客作为学习…

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…

简单的数据结构:栈

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

黑马头条vue2.0项目实战(一)——项目初始化

1. 图标素材&#xff08;iconfont简介&#xff09; 制作字体图标的工具有很多&#xff0c;推荐使用&#xff1a;iconfont-阿里巴巴矢量图标库。 注册账户 创建项目 可以根据项目自定义 class 前缀 上传图标到项目 生成链接&#xff0c;复制 css 代码&#xff0c;在项目中使用…

【知识梳理】Shell的变量计算

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 Shell中有很多变量的计算&#xff0c;会用到多种运算符。例如这几种&#xff1a; 1. Shell中常见的算术运算符 运算符意义&…

github-page静态网页将字符串写入github库中文本文档

🏆本文收录于《CSDN问答解惑-专业版》专栏,主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!! 问题描述 github-page静态…

Natutre Methods|单细胞+空间转录,值得去复现的开源单细胞分析pipeline

肺癌是全球第二大最常见的癌症&#xff0c;也是癌症相关死亡的主要原因。肿瘤生态系统具有多种免疫细胞类型。尤其是髓系细胞&#xff0c;髓系细胞普遍存在&#xff0c;并且在促进疾病方面发挥着众所周知的作用。该篇通过单细胞和空间转录组学分析了 25 名未经治疗的腺癌和鳞状…

网络模型优化——从参数向量到性能提升的最优化之旅

网络模型优化——从参数向量到性能提升的最优化之旅 网络模型优化的核心作用 组件/步骤描述参数向量网络模型中的可学习部分&#xff0c;决定了模型的输出泛函最优化通过调整参数向量以最小化或最大化某个目标函数的过程目标函数用于评估模型性能的指标&#xff0c;如损失函数…

【初阶数据结构篇】顺序表的实现(赋源码)

文章目录 本篇代码位置顺序表和链表1.线性表2.顺序表2.1 概念与结构2.2分类2.2.1 静态顺序表2.2.2 动态顺序表 2.3 动态顺序表的实现2.3.1动态顺序表的初始化和销毁及打印2.3.2动态顺序表的插入动态顺序表的尾插动态顺序表的头插动态顺序表的在指定位置插入数据 2.3.3动态顺序表…