一 串的定义和基本操作
那经过刚才的学习,不难发现,其实串字符串这种数据结构,它的逻辑特性看起来和我们之前学习的线性表是非常相似的。线性表也是由多个数据元素组成的有序序列。事实上,串它也是一种特殊的线性表。各个数据元素之间,也就是各个字符之间,也是呈现了这种线性的关系。那它们俩的区别在于普通的线性表,它里边存放的这些数据元素可以是各种各样的数据类型。是不做限制的,而串或者说字符串这种数据结构,它的各个数据元素一般来说就是字符。
比如说中文字符,英文字符,数字标点等等。所以串这种数据结构,它其实是对里边存储的这些数据元素的,数据类型有了一个限制。另一个方面,当我们在探讨线性表的基本操作,也就是增删改查那些操作的时候,我们通常探讨的是要增加或者删除或者查询线性表当中的某一。一个单独的数据元素,而我们对字符串的增删改查,这些基本操作,我们通常是要以子串为操作对象。那刚才说过,
所谓的子串,其实就是这个串里边某几个连续的数据元素的一个有序序列。就是说我们要对串这种数据结构执行增删改查的话,那通常是对这样的一堆数据元素进行增删改查。
你往搜索引擎里面输入了这样的一个字,符串的时候其实就相当于你告诉这个搜索引擎说你去找一找哪些文章,里边包含了这个字串,
那其实我们网络里边的这些。一段一段的文字信息,它本身就是一个很长的字符串,对吧?那搜索引擎做的事情就是从这些大量的字符串里面帮你找到包含了你给出的这个子串的。那些信息好,那这是对串的一个查询操作,是以子串为操作对象的那对字符串的增删改,
除了这些英文字母之外,呃,像我们的中文汉字还有其他一些少数民族语言,或者比如说像法语,日语之类的。不同国家的语言都会有自己的各自的字符。比如说像我们中文里边这样的一个汉字,
其实就是一个中文的字符,如果想用计算机二进制嘛来表示这些中文字符的话,那显然这样八个比特位的二进制数就不够用了。因为八个比特位的二进制数,它只能表示二的八次方,也就是256个状态。而我们的中文汉字,它有好几万个,所以256个状态是不足以区分这几万个汉字的,因此就有一帮人提出了一个更广泛的。字符的集合,比如说像uni co的字符集,那像uni co的字符集里边就包含了我们的什么数字英文字母,当然还有我们的中文的汉字的字符。
其实对于同一个字符集来说,你可以设计不同的编码方案,比如说大家最熟悉的是utf 8,这种编码方案当然还有utf 16等等。其实可以从数学函数的角度来理解字符集编码,你可以把字符集理解为这个函数,它的定义域。也就是里边有可能出现哪些x的值,有可能出现哪些字符,它是一个定义域,然后所谓的编码规则,比如说utf 8还有什么ask编码?这些编码规则就相当于是你这个函数里边的映射规则f,你确定了这个映射规则之后就可以把定义域里边的x值把它映射为与之对应的y值。那么,
这个y值其实就是计算机里边的这些二进制数
那这个地方再补充一点就是,如果你采用不同的编码规则的话,那么你的每个字符它所占用的空间。大小是不同的,比如说你采用ASCII码,这样的编码规则,那每一个字符,它只占一个字节。而如果你用utf 8这种编码规则的话,那你的一个中文字符可能是占三个字节。不过我们考研当中其实只需要考虑这种英文字母的情况,也就是说每一个字符它只占一个字节。好,那这是给跨考同学的一个小小的拓展,
那既然聊到编码问题,我们干脆就再聊一些东西来看一下大家遇到过的这些文件乱码的问题。应该都遇到过吧,这种情况你打开某个文件的时候,发现里边的东西是一堆乱码,你都看不懂是什么意思?那很多时候产生这种乱码问题的原因其实就在于你的软件,它解码的方式出现了错误,什么意思呢?比如说在你存储你这个文件的时候。你本来是采用某一套编码规则,也就是某一个映射函数。映射规则把这些字符映射为了相对应的二进制数,比如说在你的这套规则里边。马这个字符。
把它映射为二进制数,那对应这样的一堆东西,但是当你用另一个软件来打开你刚刚创建的这个文本文件的时候,也许你的这个软件它会以为你采用的是另一套的编码规则。那在另一套的编码规则当中,可能这一串二进制数就会被映射为这样的一个奇怪的字符。所以这才导致了你在这个地方看到的是这样的一堆一堆的乱码。
那这个小节当中,我们介绍了串这种数据结构,它在逻辑上呈现出什么样的特性?还有需要实现哪些基本操作?那在这个章节之后的内容当中,我们会花很多的篇幅来研究和子串相关的算法。那具体来说,其实就是这个算法。也就是怎么在一个主创s当中找到它的主创t的位置,那具体怎么做,我们会用之后更多的小节来进行进一步的探索。那跨考的同学还需要特别注意怎么比较两个字符串它的大小,它在计算机底层其实就是对一堆二进制数的一个比较。那具体怎么做呢?可以想一想大家背的四六级词汇的那个顺序版的词汇表,
它是怎么排序的?好了,那么以上就是这一小节的全部内容。
二 串的存储结构
我们提到过串,其实是一种特殊的线性表,所以我们可以用什么样的存储结构来实现线性表?同样的就可以用什么样的存储结构来实现串,只不过线性表当中存储的是Elemtype啊,某一种数据元素。但是串里边我们把Elemtype改成char不就行了,对吧?用它来存储字符
那这个小节当中我们介绍了串的存储结构。分别是顺序存储和链式存储,而顺序存储又分为静态数组的实现和动态数组的实现。这些存储结构的具体实现和线性表是一模一样的,所以我们就不再多说。那需要再次强调的是,我们的王道教材当中使用的是这样的一种方案,就是会把叉零这个位置给浪费掉。
然后用一个单独的lens变量来记录这个字符串的长度,所以我们之后的示例代码也会基于这样的一种设计方案来实现。那确定了具体的存储结构之后,同学们就可以尝试着自己实现一遍这些重要的基本操作,对于代码基础不好的同学,你自己动手做一做这样的练习其实是。可以有助于提高你的代码能力的,那这个小节当中我们是使用了一些基本操作来实现了,求一个串在主串当中的位置就实现了这个函数。从下一小节开始,我们会探讨不使用这些基本操作,而是直接来操作这个数组,然后用这种方式来实现index函数。