数据结构(十一)— 串

串的定义

上一章我们说了栈与队列这种基础的数据结构,这一章我们简单的来说说另一种数据结构:,首先我们来了解下串是什么?
串( string )是由零个或多个字符组成的有限序列,又名叫字符串。

一般记为 s= “a1a2…… .an” (n>=0) , 其中, s 是串的名称,用双引号(有些地方也用单引号)括起来的字符序列是串的值,注意单引号不属于串的内容。 ai(1 =< i <= n) 可以是字母、 数字或其他字符, i 就是该字符在串中的位置。 串中的字符数目 n 称为串的长度, 定义中谈到"有限"是指长度 n 是一个有限的数值零个字符的串称为空串 (null string) , 串的长度为零,可以直接用两双引号 " “” " 表示。所谓的序列,说明串的相邻字符之间具有前驱和后继的关系。

还有一些概念需要解释。
空格串,是只包含空格的串。注意它与空串的区别,空格串是有内容有长度的,而且可以不止一个空格。
子串与主串, 串中任意个数的连续字符组成的子序列称为该串的子串,相应地,包含子串的串称为主串。子串在主串中的位置就是子串的第一个字符在主串中的序号。
举个例子: “over” 、 “end”、“lie” 其实可以认为是 “lover” 、 “friend” 、 “believe” 这些单词字符串的子串。

串的抽象数据类型

串的逻辑结构和线性表很相似,不同之处在于串针对的是字符集,也就是串中的元素都是字符,哪怕串中的字符是 “123” 这样的数字组成,或者 “2010-10-10” 这样的日期组成,它们都只能理解为长度为 3 和长度为 10 的字符串,每个元素都是字符而已。
因此,对于串的基本操作与线性表是有很大差别的,线性表更关注的是单个元素的操作,比如查找一个元素,插入或删除一个元素,但串中更多的是查找子串位置、 得到指定位置子串、替换子串等操作。

串的存储结构

串的存储结构与线性表相同,分为两种:顺序存储与链式存储

顺序存储结构

串的顺序存储结构是用一组地址连续的存储单元来存储串中的字符序列的。按照预定义的大小,为每个定义的感变量分配一个固定长度的存储区。一般是用定长数组来定义。

既然是定长数组,就存在一个预定义的最大串长度, 一般可以将实际的串长度值保存在数组的 0 下标位置,有的书中也会定义存储在数组的最后一个下标位置。但也有些编程语言不想这么干,觉得存个数字占个空间麻烦。它规定在串值后面加一个不计入串长度的结束标记字符,比如”\0",来表示串值的终结,这个时候,你要想知道此时的串长度,就需要遍历计算一下才知道了,其实这还是需要占用一个空间,何必呢。如图所示:
在这里插入图片描述

链式存储结构

对于串的链式存储结构,与线性表是相似的,但由于串结构的特殊性,结构中的每个元素数据是一个字符,如果也简单的应用链表存储串值, 一个结点对应一个字符,就会存在很大的空间浪费。 因此,一个结点可以存放一个字符,也可以考虑存放多个字符,最后一个结点若是未被占满时,可以用”#“ 或其他非串值字符补全,如下图所示:
在这里插入图片描述
当然,这里一个结点存多少个字符才合适就变得很重要,这会直接影响着串处理的效率,需要根据实际情况做出选择。
但串的链式存储结构除了在连接串与串操作时有一定方便之外,总的来说不如顺序存储灵活,性能也不如顺序存储结构好。

串的匹配算法

其实串最主要的作用是用来做字符串连接、插入、复制与匹配等,其中的连接,插入,复制都是很简单的,但是匹配就比较复杂了,其中涉及到了匹配算法的问题,但是很抱歉,我看了关于字符串的朴素匹配算法与KMP模式匹配算法,感觉自己勉强能理解,本来尝试着写了一些,但是和别人相比真的感觉差距太大,怕这里写出来误认子弟,这里推荐一个我觉得说得很好的博主说的KMP匹配算法,同时这个博主的其余算法知识也是相当值得学习的。
《从头到尾彻底理解KMP》https://blog.csdn.net/v_july_v/article/details/7041827

总结回顾

这一章节我们主重点讲了 “串” 这样的数据结构,串 (string) 是由零个或多个字符组成的有限序列,又名叫字特串。 本质上,它是一种线性表的扩展,但相对于线性表关注一个个元素来说, 我们对串这种结构更多的是关注它子串的应用问题,如查找、 替换等操作。现在的高级语言都有针对串的函数可以调用。 我们在使用这些函数的时候,同时也应该要理解它当中的原理,以便于在碰到复杂的问题时,可以更加灵活的使用,比如 KMP 模式匹配算法的学习,就是更有效地去理解 index 函数当中的实现细节。多用心一点,说不定有一天,可以有以你的名字命名的算法流传于后世。

posted @ 2019-05-21 10:24  Z_WOLF  阅读(517)  评论(0编辑  收藏  举报