串、数组和广义表
串的定义
串(string):由零个或多个字符组成的有限序列(线性存储的一组数据,默认是字符)
空串:零个字符的串 用“空集符”表示
子串:串中任意个连续的字符组成的子序列 主串:包含子串的串
空格串:由一个或多个空格组成的串
4.1病毒感染检测
人的DNA序列是线性的,病毒DNA序列是环状的,eg:病毒DNA序列为aab,则人类DNA序列出现aab、aba、baa都显示被感染将病毒DNA序列看为子串,人类DNA序列看为主串进行比对
串的类型定义、存储结构及运算
串的抽象类型定义
串的存储结构
顺序存储(使用较多)
定长顺序存储
堆式顺序存储
链式存储
每个结点可以存放一个字符,也可以存放多个字符
由于串长不一定是结点大小的整倍数,则链表中的最后一个结点不一定全被串值占满,此时通常补上"#"或其他的非串值字符
串的模式匹配算法
字串的定位运算通常称为串的模式匹配或串匹配
S主串:正文串 T子串:模式
BF算法:
算法步骤
1)分别用计数指针i和j指示主串S和模式T中当前正待比较的字符位置,i初值为pos,j初值为1
2)如果两个串均未比较到串尾,即i和j均分别小于等千S和T的长度时,则循环执行以下操作:
-S[i].ch和T[i].ch比较,若相等,则i和j均分别指示串中下个位置,继续比较后续字符
-若不等,指针后退重新开始匹配,从主串的下一个字符(i=i-j+2)起再重新和模式的第一个字符(j=1)进行比较
3)如果j>T.length,说明模式T中的每个字符依次和主串S中的一个连续的字符序列相等,则匹配成功,返回和模式T中第一个字符相等的字符在主串S中的序号(i-T.length);否则称匹配不成功,返回0
最好情况:每趟不成功的匹配都发生在模式串的第一个字符与主串中相应字符的比较 主串的长度为n,子串的长度为m,平均比较次数=(n+m)/2
最坏情况: 每趟不成功的匹配都发生在模式串的最后一个字符与主串中相应字符的比较 平均比较次数=m*(n-m+2)/2
KMP算法:
的最大特点是指示主串的指针不需回溯,整个匹配过程中,对主串仅需从头至尾扫描一遍,这对处理从外设输入的庞大文件很有效,可以边读入边匹配, 而无需回头重读
数组
数组是由类型相同的数据元素构成的有序集合,每个元素称为数组元素
数组的顺序存储:数组是一种随机存取结构
以列序为主序的存储方式
以行序为主序的存储方式
特殊矩阵的压缩存储
为多个值相同的元只分配一个存储空间,对零元不分配空间
特殊矩阵:
对称矩阵:aij = aji (1<=i,j<=n) 将行序为主序存储其下三角(包括对角线)中的元
三角矩阵:
对角矩阵:所有非零元都集中在以主对角线为中心的带状区域中,可按某个原则(以行为主,或以对角线的顺序)将其压缩储存到一维数组上
稀疏矩阵:零元数目远远多于非零元数目,且非零元分布没有规律
typedef struct{ int i;//行下标 int j;//列下标 ElemType value;//非零元素值 }node; typedef struct{ int lines;//行数 int columns;//列数 int non-zeros;//非零元素个数 node *data;//用于存储非零元素的一维数组,数组空间在初始化时再申请 }sparseArray;
广义表
定义
LS=(a1,a2,...,an) LS是名称,n为长度,ai可以是单个元素或是广义表,分别称为LS的原子(小写)和子表(大写)
typedef struct GNode *GList; typedef struct{ int tag;// 标志域 原子结点tag=0 表结点tag=1 union{//子表指针域SubList与单原子数据域Data复用,即共用存储空间 ElemType Data; GList SubList; }URegion; GList Next;//指向后继节点 }GNode;
结论
1)广义表的元素可以是子表,而子表的元素还可以是子表
2)广义表可为其他广义表共享
3)广义表可以是一个递归的表
运算
1)取表头GetHead(LS) 取非空广义表的第一个元素(单原子/子表)
2)取表尾 GetTail(LS) 取出的表尾为除去表头之外的其余元素,所以一定是广义表
存储结构
头尾链表的存储结构
原子结点:标志域(tag=0)和值域(atom)
表结点:标志域(tag=1)、指示表头的指针域(hp)和指示表尾的指针域(tp)
扩展线性链表的存储结构
在原子结点后增加了尾指针
——————————————————————————————
本周小结:本周的内容基本都是建立在原有知识的基础上,之前没有接触到的广义表也比较好理解,特殊的是广义表可以递归,子表也可以是表元素。本章最重要的部分就是串的模式匹配,主要运用了BF算法和KMP算法,前者虽然时间复杂度比较高,但是在数据量较小的时候不会造成很大影响。KMP算法是最难理解的部分,特别是对于next的理解与计算,所以需要花更多时间去消化。
推荐:关于KMP算法大家可以去b站看一下 BV1jb411V78H 不涉及具体的代码实现,但是对于算法的思路讲的比较清晰