「笔记」《大话数据结构》第五章:串

版权声明:欢迎转载,转载请注明出处。 如果本文帮助到你,本人不胜荣幸,如果浪费了你的时间,本人深感抱歉。如果有什么错误,请一定指出,以免误导大家、也误导我。感谢关注。 https://blog.csdn.net/Airsaid/article/details/78670835

本文笔记来自《大话数据结构》

什么是串

串(string):是由零个或多个字符组成的有限序列,又名叫做字符串。

一般我们用 “abcde…” 来表示一个串,就是用 “” 双引号将一些字符括起来。abcde 这些就是被括起来的字符,可以是数字、符号、字母或者其他的字符。

串的长度是有限的。零个字符的串被称为空串(null string),可以用 “” 表示,长度为 0。

串的相邻字符之间具有前驱和后继的关系。

另外还有一些概念:

  • 空格串:只包含空格的串,注意这并不是一个空串,空格串是有长度的,而且可以不止一个空格。
  • 子串与主串:子串就是由主串中任意个数连续字符组成的。子串在主串中的位置就是子串中第一个字符出现的位置。

串的比较

两个数字之间很容易比较大小。那么两个串之间,该如何比较谁大谁小呢?

事实上,串的比较是通过比较组成串的字符之间的编码来进行的,而字符的编码指的是字符在对应字符集中的序号。

在计算机中,常用编码有 ASCLL、 Unicode 等。假如我们要比较:”happen” 和 “happy” 哪个串比较大的话,那么就会先将每个串的字符拿出来进行比较,其中 h、a、p、p 这几个字符都是相等的,就看 e 和 y 字符了,由于 e 字符的 ASCLL 码是 101,而 y 字符的 ASCLL 码则是 121,于是 “happen” < “happy”。

串的抽象数据类型

ADT 串(string)
Data
    串中元素仅由一个字符组成,相邻元素之间具有前驱和后继关系。
Operation
    assign(T, *chars):生成一个其值等于字符串常量 chars 的串 T。
    copy(T, S):串 S 存在,由串 S 复制得串 T。
    clearString(S):若串 S 存在,将串清空。
    isEmpty(S):若串 S 为空,返回 true,否则返回 false。
    length(S):返回串 S 的元素个数,即串的长度。
    compare(S, T):比对串 S 与 T,若 S > T,返回值 > 0,若 S == T,返回 0,若 S < T,返回值  < 0。
    concat(T, s1, s2):连接 s1 与 s2 形成新串 T。
    subString(Sub,  S, pos, len):若串 S 存在,截取串 S 从 pos 位置到 len 长度的新串,并用 Sub 返回。
    index(S, T, pos):若主串 S 中存在和串 T 值相同的字串,则返回它在主串 S 中第 pos 个字符之后第一次出现的位置,否则返回 0.
    replace(S, T, V):用 V 替换主串 S 中出现的所有与 T 相等的不重叠的子串。
    insert(S, pos, T):在串 S 的第 pos 个字符之前插入串 T。
    delete(S, pos, len):从串 S 中删除第 pos 个字符起长度为 len 的子串。
 endADT

串的存储结构

串的顺序存储结构

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

为了避免长度的限制,于是在对与串的顺序存储,有一些变化,串值的存储空间可在程序执行过程中动态分配可得。比如在计算机存在一个自由存储区,叫做 “堆”。通过 “堆” 可以进行串的动态分配操作。

串的链式存储结构

对于串的链式存储结构,与线性表是相似的,但是由于串结构的特殊性,串的每个元素都是一个字符,如果也简单的应用链表存储串值,一个结点对应一个字符,则会存在很大的空间浪费。

因此,一个结点可以考虑用一个结点存放一个字符,也可以考虑存放多个字符。比如说,一个结点存储 4 个字符,若最后一个结点未被占满时,用 “#” 或其他非串值字符补全。

当然,这里到底应该一个字节存储多少字符才合适就会变得很重要,这会直接影响串的处理的效率,需要根据实际情况作出选择。但串的链式存储结构除了在连接串与串操作时有一些方便之外,总的来说不如顺序存储结构灵活,性能上也不如顺序存储好。

朴素的模式匹配算法

当我们想在某一段文章中找出某一句或者某个词,那么实际上就相当于在主串中查找对应的子串。
这种子串的定位操作通常被称为:串的模式匹配

当我们想在 “goodgoogle” 中找出 “google” 这个子串的位置。我们就需要一位一位进行对比匹配,以主串的每一个字符作为子串开头,与要匹配的字符串进行匹配。对主串做大循环,每个字符开头做小串的小循环,直到匹配成功或全部遍历完成为止。因此,朴素模式匹配算法很低效。

KMP 模式匹配算法

KMP 模式匹配算法是由 D.E.Knuth、J.H.Morris 和 V.R.Pratt (其中 Knuth 和 Pratt 共同研究,Morris 独立研究)发表的一个模式匹配算法,可以大大避免重复遍历的情况,我们把它简称为克努特—莫里斯—普拉特算法,简称 KMP 算法。

KMP 算法原理

KMP 算法的原理就在于省略那些不必要的判断。

举个例子,假如我们现在要匹配 P 串 “abcdeg” 与 C 串 “abcm”,后者是前者的子串。

在第一遍比对的时候,我们发现 P 串的前三位 “abc” 与 C 串的 “abc” 是相等的,但是在第四位的时候却不相等了。

C 串的 “adc” 这几个字母都没有重复,那么也就意味着,下次判断时,子串不用再往右移动一位再拿 “a” 和 P 串 “b” 进行比较,因为肯定是不相等的,直接跳到用 “a” 与 “d” 比较即可。

总结

串(string):是由零个或多个字符组成的有限序列,又名叫做字符串。
本质上它是线性表的扩展,但对于线性表关注一个个元素来说,它更多的关注的是它子串的应用问题,比如查找、替换等操作。

猜你喜欢

转载自blog.csdn.net/Airsaid/article/details/78670835
今日推荐