一、什么是串

串就是我们常说的字符串,它同样是一个线性表。可能有人认为串就是元素为字符的线性表,但这种说法是不准确的。对于普通的线性表,它们关注的往往是单个元素,每个单独的元素都有独立的含义。比如我们用线性表存储班级成绩,那么元素类型的定义应该如下:

typedef struct{char num[10]; //学号char name[10];  //姓名float scores;   //分数
}

假设表中存储了下面几个个元素:

学号 姓名 分数
1809111001 zack 97.5
1809111002 rudy 94
1809111003 alice 96
1809111004 atom 99

现在我们拿出学号为0104两个人的数据,我们只会说是两个人的成绩,或者排名前面的两个人。而不是用一个整体来称呼它们(通常情况是这样的)。

对于串来说,则有些不一样。比如下面这个字符串:

Do not go gentle into that good night!

我们取出一部分数据:

gentle

我们可以把它称为单词,我们再取出一部分:

good night!

我们可以说它是一个句子。正是因为串各的某个部分有整体意义,在串中我们需要实现对字串模式的操作。后面会详细介绍。

二、串的表示

这里我们使用顺序存储结构来表示一个串,结构和顺序表类似:

#define MAXSIZE 20
typedef struct{char ch[MAXSIZE+1];int length;
}SString;

这里我们创建了一个长度为MAXSIZE+1的char数组。其中下标为0的元素我们不存储数据,这是为了让逻辑位置和物理位置对应。其它和顺序表则是一样的。

除了上面的表示,还可以采用和C语言本身字符串一样的表示。我们不存储长度信息,而是通过\0这个字符来表示结尾。不过这种方式获取字符串长度的算法时间复杂度是O(n)。

三、串的实现

(1)串的赋值

串的赋值非常简单,就是一个简单的循环操作:

void StringAssign(SString *S, char *str){int i = 0;//如果当前字符不是\0while (s[i] != '\0'){//将字符数组的内容赋值给串S->ch[i+1] = s[i];++S->length;++i;}
}

因为数组的下标是从0开始的,因此将s[i]赋值给S->ch[i+1]。

(2)串的复制

复制操作和赋值操作类似,同样是一个简单的循环,只不过将赋值内容改成了一个串:

int StringCopy(SString *S1, SString S2){//如果串为空,则返回0if (!S2.length){return 0;}//循环遍历S2,将S2内容依次赋值给S1for(int i = 1; i <= S2.length; i++){S1->ch[i] = S2.ch[i];}//修改被赋值串S1的长度S1->length = S2.length;return 1;
}

我们不需要在意S1原本的内容,只需要将内容依次覆盖,然后修改S1的长度即可。这样逻辑上我们已经完成了串的赋值。而物理上S1的尾部可能有其它字符,不过我们不需要在意。

(3)求长度

我们直接返回串的length成员即是长度:

int StringLength(SString S){return S.length;
}

(4)串比较

串的比较就是各个字符ASCII数值的比较:

int StringCompare(SString S1, SString S2){//遍历S1,依次比较S1和S2的每个字符for(int i = 1; i < S1.length; i++){//如果不是同一个字符if(S1.ch[i] != S2.ch[i]){//返回它们的差值return S1.ch[i] - S2.ch[i];}}//返回长度的差值return S1.length - S2.length;
}

在循环中,我们判断了字符是否一样。如果不一样则返回S1当前字符和S2当前字符的差。我们判断字符串是通过第一个不匹配的字符来判断的。比如下面几对:

abc    >    abd
acd    >    add

如果每个对应字符都匹配成功,则比较串的长度。这里返回的是长度的差值,如果两个串一样,那函数会返回0。如果S1“大于”S2,那函数会返回大于0的数,否则返回小于0的数。

(5)截取字串

子串就是串中任意个连续的字符组成的串,比如我们有一个串:

Do not go gentle into that good night!

下面几个都是它的子串:

Donot
t go gentle
good

子串必须存在与原串,而且必须连续。

截取子串的操作很简单,这里只是单纯通过下标来截取:

int SubString(SString S1, SString *S2, int pos1, int pos2){//如果下标不合理,则返回0if(pos1 < 1 || pos2 > S1.length || pos2 <= pos1){return 0;}//将S1被截取的内容依次赋值给S2for(int i = pos1, j = 1; i <= pos2; i++, j++){S2->ch[j] = S1.ch[i];}//修改S2的长度S2->length = pos2-pos1;return 1;
}

下面我们来单独看两个操作,定位字串和模式匹配。

四、定位字串和模式匹配

定位子串的操作就是找到子串第一次出现在原串中的位置,比如我们有下面几个子串:

Do not go gentle into that good night!
Do
not
nt

其中Do的位置为1,not的位置为4,而nt在串中出现了两次,我们用第一次出现的位置表示,即13。下面我们就来看看怎么查找字串。

(1)定位子串

定位子串的操作就是不断对比串的过程,我们最开始将原串的指针i指向串首,取i到i+len的串与子串比较(其中len是子串的长度)。如图:

其中红框部分就是取出来与子串比较的部分。如果与子串相等,我们就返回i作为子串在原串中的位置。如果失败,则i++,直到i+len大于原串的长度。

代码实现如下:

int IndexSubString(SString S1, SString S2){//用于存储原串截取的部分SString temp;InitString(&temp);//如果子串长度大于if(S1.length < S2.length){return 0;}//循环比较原串和子串for(int i = 1; i+S2.length <= S1.length; i++){//截取原串内容SubString(S1, &temp, i, i+S2.length);//将截取内容与子串比较int result = StringCompare(temp, S2);//如果截取内容与子串相等,则返回i的值(子串的位置)if(result == 0){return i;}}return 0;
}

通常定位子串的前提是子串一定能在原串中找到。而上面是考虑了子串不存在的情况。而我们无法确定子串是否能在原串中找到时做的定位操作叫模式匹配。不过模式匹配还包括了一些特殊规则的匹配、因此模式匹配的含义要更丰富。

(2)模式匹配

上面的算法我们特意截取出一个临时串用于比较,这一步其实是没必要的,这里为了让大家看代码更轻松才这样安排。不借助辅助串的代码如下:

int IndexSubString(SString S, SString T) {//指向被比较子串的首位置int k = 1;//分别指向原串中被比较的位置和模式串中被比较的位置int i = k, j = 1;//循环比较while (k <= S.length && j <= T.length){if(S.ch[i] == T.ch[j]){//当前字符匹配成功则继续匹配i++;j++;}else{//当前字符匹配失败则将k指向下一个子串,i与k同步k++;i=k;j=1;}}//防止原串字符不够if(j > T.length)return k;elsereturn 0;
}

k、i、j三个指针指向的位置如图所示:

而在循环过后我们还判断了j是否大于S2.length,这里大家可以模拟匹配下面串的过程:

abaccdo
cdoo

当我们匹配到末尾时,循环可以正常退出。但是j指针指向模式串的第一个o,这时我们算法应该返回匹配失败的信号。这就是最后的if语句的作用了。

准确来说,上面两个算法都是模式匹配算法。在串中还有一个重要的KMP算法,由于篇幅限制,KMP算法将单独写一篇文章。

【C语言数据结构7】--串的实现相关推荐

  1. 用数据结构c语言写成绩排序,C语言数据结构 快速排序实例详解

    C语言数据结构 快速排序实例详解 一.快速排序简介 快速排序采用分治的思想,第一趟先将一串数字分为两部分,第一部分的数值都比第二部分要小,然后按照这种方法,依次对两边的数据进行排序. 二.代码实现 # ...

  2. matlab高级数据结构,Matlab讲义-第四章Matlab语言数据结构1-10.pdf

    Matlab讲义-第四章Matlab语言数据结构1-10.pdf 第四章第四章 Matlab语言基础语言基础 Matlab语言程序简洁.可语言程序简洁.可 读性很强而且调试十分容易.读性很强而且调试十 ...

  3. Python 数据结构 之 串 的链式存储结构

    本文所采用的数据结构模板为 <数据结构教程>C语言版,李春葆.尹为民等著. 改篇所涉及到的是 串 的链式存储结构. 用Python仿照C语言来实现. 文章转载请注明:  Python 数据 ...

  4. 数据结构:串、数组和广义表

    串 线性结构:线性表.栈和队列.串与数组和广义表 串的逻辑结构和线性表极为相似,区别仅在于串的数据对象限定为字符集.在基本操作上,串和线性表有很大差别.线性表的基本操作主要以单个元素作为操作对象,如查 ...

  5. 快速排序【C语言数据结构】

    目录 一.快速排序的基础实现 1.经典写法 2.挖坑法 3.前后指针法 二.快速排序第二部分的写法 三.优化我们基准值的选取 四.快速排序的非递归写法 五.代码的汇总 六.测试代码 快速排序,顾名思义 ...

  6. c语言将一个已知头结点的单链表逆序_C语言数据结构实现链表逆序并输出

    C语言数据结构实现链表逆序并输出 将一个链表逆序并输出.我用了两种方法来实现,第一种是借助了一个新的空链表:第二种是在原来链表的基础上直接实现逆序. 实例代码: 头文件: #include #incl ...

  7. 数据结构c语言版第一章答案,《c语言数据结构》第一章概论自测题答案

    <<c语言数据结构>第一章概论自测题答案>由会员分享,可在线阅读,更多相关<<c语言数据结构>第一章概论自测题答案(4页珍藏版)>请在人人文库网上搜索. ...

  8. 一些可运行的C语言数据结构代码

    网上有很多C语言数据结构代码:有的不能运行:下面是一些能运行的,和运行截图:备用一下: 1 队列 #include<stdio.h> #include<stdlib.h>#de ...

  9. C语言数据结构学习用单元测试

    药物名称: C语言数据结构学习用单元测试 主治: 本品是基于CUnit编写的.全部的.纯C的数据结构(ADT)各种实现的单元测试.主治基础不牢,水品增长缓慢.建议配合严蔚敏<数据结构>(C ...

  10. 顺序表输入栈元素c语言,C语言数据结构之栈简单操作

    C语言数据结构之栈简单操作 实验: 编写一个程序实现顺序栈的各种基本运算,并在此基础上设计一个主程序,完成如下功能: (1)初始化顺序栈 (2)插入元素 (3)删除栈顶元素 (4)取栈顶元素 (5)遍 ...

最新文章

  1. UIView层次管理(sendSubviewToBack,bringSubviewToFront)
  2. [OS复习]进程管理5
  3. Rabbit寻宝记(2)
  4. FreeMarker生成word的代码
  5. 试述大数据对思维方式的重要影响
  6. 手机恢复出厂设置命令_擦除数据/恢复出厂设置通过ADB
  7. sharepoint文件夹本地同步_mac文件同步软件-Resilio Sync Home
  8. 详述SaltStack Salt 命令注入漏洞(CVE-2020-16846/25592)
  9. linux 配置redis密码
  10. python 中不属于数据挖掘分析模块的是()_大工19秋《数据挖掘》在线作业3(参考答案)...
  11. Linux下PHP开发环境搭建(Apache2.4+PHP7.1+MySQL8.0)
  12. 土壤类型空间分布数据介绍
  13. 教程 ios 4 以上安装mobile terminal的最简单方法
  14. 走向世界中的我国摄影测量与遥感 ——访中国测绘学会理事长、国家测绘局原副局长杨凯
  15. vue3 + vite +ts 引入静态图片
  16. vue怎么使用eval_eval()的使用和兼容性问题
  17. Win11怎么设置共享文件夹?Win11共享文件夹设置方法
  18. oracle归档日志存储路径,oracle 归档日志路径三个参数DB_RECOVERY_FILE_DEST和LOG_ARCHIVE_DEST和LOG_ARCHIVE_DEST_n的关系...
  19. 64位操作系统支持的最大内存
  20. Chrome浏览器使用指南

热门文章

  1. 032-IDUtils 工具类模板
  2. 让我们用心感受泛型接口的协变和抗变out和in
  3. 用UltraEdit软件替换回车换行的窍门
  4. 【云计算】Netflix 开源持续交付平台 Spinnaker
  5. UVA 10602 - Editor Nottoobad
  6. 计算机中dhcp服务器怎么找,如何查找网络中其他非法 DHCP 服务器Unix系统 -电脑资料...
  7. Qt 获取qrc文件列表
  8. python将txt转为字符串_一文搞懂Python文件读写
  9. QtextEdit自定义右键菜单
  10. QT制作动画收缩效果