《数据结构》第四章
文章目录
4.1 串的定义
串和字符串是由零个或多个字符组成的有限序列;
串中字符的数目n称为串的长度;
零个字符的串称为空串;
串中任意个连续的字符组成的子序列称为该串的子串;
包含子串的串相应的称为主串;
当且仅当两个串的值相等,称为这两个串是相等的;
由一个或多个空格组成的串” “称为空串;(无空格,无任何元素)
4.2 案例引入
4.3 串的类型定义,存储结构及其运算
串的逻辑结构和线性表极为相似,区别仅在于串的数据对象约束为字符集;
线性表大多以”单个元素“为操作对象,串是以”串整体“为研究对象;
4.3.1 串的抽象类型定义
4.3.2的存储结构
串的两种基本存储结构:顺序存储和链式存储;
1.串的顺序存储
类似与线性表的顺序存储结构,用一组地址连续的存储单元存储串值的字符序列;
注意:算法描述当中所用到的顺序存储的字符串都是下标为1的数组分量开始存储的,下表为0的分量闲置不用;
2.串的链式存储
由于串结构的特殊性——结构中的每个元素是一个字符,则用在链表存储串值时,存在
一个”结点大小“问题,即每个检点可以存放一个字符,也可以存放多个字符;
为了便于进行串的操作,当以链表存储串值时,除头指针外,还可附设一个尾指针指示链表
中的最后一个结点,,并给出当前串的长度;
优点:串值的链式存储结构对某些串操作,如连接操作等有一定方便之处;
缺点:不如顺序存储结构灵活,它占用存储量大且操作复杂;
4.3.3 串的模式匹配算法
子串的定位运算同窗称为串的模式匹配或串匹配;
1.BF算法
最简单直观的模式匹配是BF算法;
模式匹配不一定是从主串的第一个位置开始,可以指定主串中查找的起始位置pos;
1.分别利用计数指针i和j指示的主串S和模式T中当前正待比较的字符位置,i初值为pos,j初值为1;
2.如果两个串均未比较到串尾,即i和j均分别小于等于S和T的长度时,则循环执行以下操作:
- S.ch[i]和T.ch[j]比较,若相等,则i和分别只是串中下一个位置,继续比较后续字符;
- 若不相等,指针后退重新开始匹配,从主串的下一个字符(i=i-j+2)起再重新和模式的第一个字符(j=1)比较;
3.如果j>T.length,说明模式T中的每一个字符相等的字符在主串的S中的一个连续的字符序列相等,则匹配成功,
返回和模式T中第一个字符相等的字符在主串S中的序号(i-T.length);否则称匹配不成功,返回0;
缺点:算法复杂度高;
2.KMP算法
KMP算法可在O(n+m)的时间数量级上完成串的模式匹配操作;
KMP算法是在已知模式串的next值的基础上执行的;
特点:KMP算法的指针不需要回溯;
说明:KMP算法是指在匹配中如果匹配不成功,将寻找与主串匹配的公共前后缀(在与主串
不匹配的元素的前一位元素到模式串的第一个元素且元素相等不唯一),从而进行继续匹配;
如若长度超过主串,则匹配不成功;
- next[]函数的作用:判断模式串的前后缀是否相等;
| 位序| 1| 2| 3| 4| 5|
|–|–|–|–|-- |–|
| 模式串| a| b| a| a| c|
| next[]值| 0| 1| | | |
- 初始化next[1]的值为0,next[2]的值为1;
- 比较基准:要求next值的前一位模式串为基准;比如此时位序为3的前一位模式串为’b’;
- 比较对象:比较基准的next值所对应的位序下的模式串;比如比较基准是位序为2的模式串’b’的next值为1,位序为1的模式串为’a’;
- 若比较基准不等于比较对象,则next值为1;反之则next值为前一位模式串的next值加1;
- nextval[]函数:是KMP算法改良所设立的函数,
j | a | b | a | c | b | d | a |
---|---|---|---|---|---|---|---|
next值 | 0 | 1 | 2 | 2 | 2 | 3 | 4 |
nextval | 0 | 1 | 2 | 2 | 0 | 3 | 4 |
nextval(next函数的修正值)
- 若第k位序的模式串与第next[k]位序所对应的模式串相等,则nextval[k] = nextval[next[k]](与其nextval值相等);
- 若不相等,则nextval[k] = next[k];
4.4 数组
特点:结构固定——定义后,维数和维界不再改变;
结论:线性表结构是数组结构的一个特例;
而数组结构又是线性表结构的扩展;
4.4.1 数组的类型定义
数组是由类型相同的数据元素构成的有序集合;
一维数组的逻辑结构:线性结构 定长的线性表;
声明格式:数据类型,变量名称[长度];
二维数组的逻辑结构:
1.非线性结构:行表+列表
2.线性结构:定长的线性表;
特点:数组一旦被定义,它的维数和维界就不再改变;
基本操作:除了结构的初始化和销毁之外,数组只有存取元素和修改元素值的操作;
4.4.2 数组的顺序存储
数组一般不进行删除或插入操作,也就是说一旦建立了数组,则结构中的数据元素
个数和元素之间的管旭一般不再发生变动;
对于数组,一旦规定了其维度和各维的长度,便可为它分配存储空间;
反之,只要给出一组下标便可求出相应数组元素的存储位置;
4.4.3 特殊矩阵的压缩存储
矩阵:一个由m*n个元素排成的m行n列的表;
压缩存储:为多个值相同的元素只分配一个存储空间,对零元素不分配;
特殊矩阵:假若值相同的元素或者零元素在矩阵中的分布有一定规律;(对称矩阵,三角矩阵,对角矩阵等)
1.对称矩阵
a(ij) = a(ji);
2.三角矩阵
三角矩阵有上三角矩阵和下三角矩阵两种;
上三角矩阵:指矩阵下三角(不包括对角线)中的元素均为常数c或0的n阶矩阵,下三角矩阵则相反;
多角形线矩阵:所有的非零元素都集中在以对角线为中心的带状区域中,即除了对角线上和直接在对角线上
下方若干条与对角线平行的线上的元素外,所有其他元素均为0;
4.5 广义表
4.5.1 广义表的定义
广义表:线性表的推广,也称为列表;
用大写字母表示广义表的名称,用小写字母表示广义表的原子;
3个重要结论
- 广义表的元素可以是子表,而子表的元素还可以是子表…由此,广义表是一个多层次的结构,可以用图像表示;
- 广义表可为其他广义表所共享;
- 广义表可以是一个递归的表,即广义表可以是自身的一个子表;
取表头:取出的表头可以是广义表的第一个元素,它可以是单原子,可以是一个子表;
取表尾:取出的表尾是广义表中除了表头元素之外由其余元素构成的表,即表尾一定是一个广义表;
4.5.2 广义表的存储结构
1.头尾链表的存储结构
由于广义表中的数据元素可能为原子或者广义表,因此需要两中结构的结点:
一种是表结点,用以表示广义表;一种是原子结点,用以表示原子;