数据结构(六)串存储结构

严格意义上讲,串存储结构也是一种线性存储结构,因为字符串中的字符之间也具有"一对一"的逻辑关系。只不过,与之前所学的线性存储结构不同,串结构只用于存储字符类型的数据。

存储一个字符串,数据结构包含以下3中具体存储结构:

1.定长顺序存储 :使用静态数组存储(定长,提前开辟内存空间)字符串。
2.堆分配存储:使用动态数组存储字符串。
3.块链存储:使用链表存储字符串。

定长顺序存储

串的定长顺序存储结构,可以简单地理解为采用 "固定长度的顺序存储结构" 来存储字符串,因此限定了其底层实现只能使用静态数组。

用定长顺序存储结构存储字符串时,需结合目标字符串的长度,预先申请足够大的内存空间。

char[] str = {'a','b','c','d','e'};

根据实际情况,实现代码可包含一些函数,用于实现某些具体功能,如求字符串的长度等,由于这些知识都是学习编程语言的基础内容,因此不再过多赘述。

堆分配存储结构

串的堆分配存储,其具体实现方式是采用动态数组存储字符串。
java中貌似没有这种字符串结构,String类中char[] 是final的 不允许变化。(StringBuilder不清楚)所以此处不做研究。

串的块链存储结构

串的块链存储,指的是使用链表结构存储字符串。
示例中实现串的块链存储使用的是无头节点的单链表。当然根据实际需要,也可以使用其它链表的结构(双向链表还是单链表,有无头节点)。

例如,图1 所示是用链表存储字符串 shujujiegou,该链表各个节点中可存储 1 个字符:

图1:各节点仅存储1个数据元素的链表

同样,图 2 设置的链表各节点可存储 4 个字符:


图2:各节点存储4个数据元素的链表

从图 2 可以看到,使用链表存储字符串,其最后一个节点的数据域不一定会被字符串全部占满,对于这种情况,通常会用 '#' 或其他特殊字符(能与字符串区分开就行)将最后一个节点填满。

链表各节点存储数据个数的多少可参考以下几个因素:

1.串长度和存储空间大小:若串包含数据量很大,且链表申请的存储空间有限,此时应尽可能让各节点存储更多的数据,提高空间利用率。

2.程序实现功能:如果实际场景中需要对存储的串做大量拆入或删除操作,则应尽可能减少各节点存储数据的数量。

以上两点仅是目前想到影响节点存储数据个数的因素,在实际场景中,还需结合实现环境综合分析。


串模式匹配算法

串的模式匹配算法,通俗地理解,是一种用来判断两个串之间是否具有"主串与子串"关系的算法。
实现串的模式匹配的算法主要有以下两种:

  • 1.普通的模式匹配算法,BF算法 (Brute Force)暴风算法
  • 2.快速模式匹配算法 KMP算法(Knuth-Morris-Pratt 三个发明者的名字)

BF算法原理

普通模式匹配算法,其实现过程没有任何技巧,就是简单粗暴地拿一个串同另一个串中的字符一一比对,得到最终结果。

首先,将串 A 与串 B 的首字符对齐,然后逐个判断相对的字符是否相等,如图3 所示:


图3:串的第一次匹配

图 3 中,由于串 A 与串 B 的第 3 个字符匹配失败,因此需要将串 A 后移一个字符的位置,继续同串 B 匹配,如图 4 所示:


图4:串的第二次匹配

图 4 中可以看到,两串匹配失败,串 A 继续向后移动一个字符的位置,如图 5 所示:


图5:串的第三次匹配

图 5 中,两串的模式匹配失败,串 A 继续移动,一直移动至图 6 的位置才匹配成功:


图6:串的第四次匹配

:

BF算法的时间复杂度

该算法最理想的时间复杂度 O(n),n 表示串 A 的长度,即第一次匹配就成功。
F 算法最坏情况的时间复杂度为 O(n * m),n 为串 A 的长度,m 为串 B 的长度。例如,串 B 为 "0000000001",而串 A 为 "01",这种情况下,两个串每次匹配,都必须匹配至串 A 的最末尾才能判断匹配失败,因此运行了 n * m 次。

BF 算法的实现过程很 "无脑",不包含任何技巧,在对数据量大的串进行模式匹配时,算法的效率很低。


KMP算法(快速模式匹配算法)

快速模式匹配算法,简称 KMP 算法,是在 BF 算法基础上改进得到的算法。

KMP 算法,它的实现过程接近人为进行模式匹配的过程。例如,对主串 A("ABCABCE")和模式串 B("ABCE")进行模式匹配,如果人为去判断,仅需匹配两次。


图7:第一次认为匹配模式

第一次如图 7 所示,最终匹配失败。但在本次匹配过程中,我们可以获得一些信息,模式串中 "ABC" 都和主串对应的字符相同,但模式串中字符 'A' 与 'B' 和 'C' 不同。

因此进行下次模式匹配时,没有必要让串 B 中的 'A' 与主串中的字符 'B' 和 'C' 一一匹配(它们绝不可能相同),而是直接去匹配失败位置处的字符 'A' ,如图 8 所示:


图8:第二次人为模式匹配

由此可以看出,每次匹配失败后模式串移动的距离不一定是 1,某些情况下一次可移动多个位置,这就是 KMP 模式匹配算法
KMP算法在此只做简述,(主要有点复杂,懒得写了)不做展开讲解。
另外还有Sunday和BM算法 建议使用Sunday算法。

你可能感兴趣的:(数据结构(六)串存储结构)