定义
零个或多个任意字符组成的有限序列
有关术语
串的顺序存储结构(数组实现)
#define MAXLIEN 255
typedef struct{
char ch[MAXLIEN+1];//串数组
int length;//串的长度
}SString;
串的链式存储–块链结构
#define CHUNKSIZE 80
typedef struct Chunk{
char ch[CHUNKSIZE];
struct Chunk *next;
}Chunk;
typedef struct{
Chunk *head,*tail;
int curlen;
}LString;
算法目的
确定主串中所含子串(模式串)第一次出现的位置(定位)
算法应用
算法种类
BF算法–穷举法
KMP算法(速度快)
BF算法**
也称为简单匹配算法–采用穷举法
算法思路–Index(S,T,pos)
将主串的第pos个字符和模式串的第一个字符比较
int Index_BF(SString S,SString T){
int i=1,j=1;
while(i<S.length&&j<=T.length){
if(S.ch[i]==T.ch[j]) ++i,++j;//匹配
else i=i-j+2,j=1;//回溯
}
if(j>=T.length) return i-T.length;//匹配成功
else return 0;//匹配不成功
}
算法设计思想
利用已经部分匹配的结果而加快模式串的滑动速度,且主串S的指针不必回溯,可提速到O(n+m)
next数组的实现
const int N=1e6+10;
int next[N];
void get_next(SString T,int &next[]){//next数组的实现
int i=1,j=0;next[1]=0;
while(i<T.length){
if(j==0||T.ch[i]==T.ch[j]){
++i,++j;
next[i]=j;
}else{
j=next[j];
}
}
}
int Index_BF(SString S,SString T,int pos){//模式匹配
int i=1,j=1;
i=pos;
while(i<S.length&&j<=T.length){
if(j==0||S.ch[i]==T.ch[j]) ++i,++j;//匹配
else j=next[j];//回溯
}
if(j>=T.length) return i-T.length;//匹配成功
else return 0;//匹配不成功
}
代码实现:
void get_nextval(SString T,int &nextval[]){
int i=1,j=0;nextval[1]=0;
while(i<T.length){
if(j==0||T.ch[i]==T.ch[j]){
++i,++j;
if(T.ch[i]!=T.ch[j])nextval[i]=j;
else nextval[i]=nextval[j];
}else{
j=nextval[j];
}
}
}
定义:按一定格式排列起来,具有相同类型的数据元素的集合
一维数组:若线性表中的数据元素为非结构的简单元素则称为一维数组。
二维数组:若一维数组中的数据元素又是一维数组结构,则称为二维数组
二 维 数 组 的 逻 辑 结 构 = { 非 线 性 结 构 : 每 一 个 数 据 元 素 既 在 一 个 行 表 中 , 又 在 一 个 列 表 中 线 性 结 构 定 长 的 线 性 表 : 该 线 性 表 的 每 个 数 据 元 素 也 是 一 个 定 长 的 线 性 表 二维数组的逻辑结构=\begin{cases} 非线性结构:&每一个数据元素既在一个行表中,又在一个列表中\\ 线性结构定长的线性表: & 该线性表的每个数据元素也是一个定长的线性表 \end{cases} 二维数组的逻辑结构={非线性结构:线性结构定长的线性表:每一个数据元素既在一个行表中,又在一个列表中该线性表的每个数据元素也是一个定长的线性表
声明格式:数据类型 变量名称[行数][列数]
三维数组:若二维数组中的元素又是一个一维数组,则称作三维数组。
n维数组:若n-1维数组中的元素又是一个一维数组结构则称作n维数组。
数组特点:结构固定一一定义后,维数和维界不再改变。
结论:线性表结构是数组结构的一个特例,而数组结构又是线性表结构的扩展。
L O C ( i ) = { L O C ( 0 ) = a i = 0 L O C ( i − 1 ) + L = a + i ∗ L i > 0 LOC(i)=\begin{cases} LOC(0)=a & i=0 \\ LOC(i-1)+L=a+i*L & i>0 \end{cases} LOC(i)={LOC(0)=aLOC(i−1)+L=a+i∗Li=0i>0
二维数组
有二维数组A[m][n]:
以行序为主序:设数组开始存储位置LOC(0,0),存储每个元素需要L个存储单元
数组元素a[i][j]的存储位置是: L O C ( i , j ) = L O C ( 0 , 0 ) + ( n ∗ i + j ) ∗ L LOC(i,j)=LOC(0,0)+(n*i+j)*L LOC(i,j)=LOC(0,0)+(n∗i+j)∗L
三维数组
a [ m 1 ] [ m 2 ] [ m 3 ] a[m_1][m_2][m_3] a[m1][m2][m3]各维元素个数为 m 1 , m 2 , m 3 m_1,m_2,m_3 m1,m2,m3
下标 i 1 , i 2 , i 3 i_1,i_2,i_3 i1,i2,i3的数组元素的存储位置:
L O C ( i 1 , i 2 i 3 ) = a + i 1 ∗ m 2 ∗ m 3 + i 2 ∗ m 3 + i 3 LOC(i_1,i_2i_3)=a+i_1*m_2*m_3+i_2*m_3+i_3 LOC(i1,i2i3)=a+i1∗m2∗m3+i2∗m3+i3–第 i 1 i_1 i1页总元素个数 + + +第 i 1 i_1 i1页的前 i 2 i_2 i2行总元素 + + +第 i 2 i_2 i2行前 i 3 i_3 i3列元素个数
特殊矩阵的压缩存储
矩阵:一个由m×n个元素排成的m行n列的表
矩阵的常规存储:将矩阵描述为一个二维数组
矩阵的常规存储特点:1.可以对其元素进行随机存取。2.矩阵运算非常简单;存储的密度为1。
不适宜常规存储的矩阵:值相同的元素很多且某种规律分布;零元素多。
什么是压缩存储
若多个数据元素的值都相同,则只分配一个元素值得存储空间,且零元素不占存储空间。
什么样的矩阵能够压缩
一些特殊矩阵,eg:对称矩阵、对角矩阵、三角矩阵、稀疏矩阵等。
什么叫稀疏矩阵
矩阵中非零元素的个数较少(一般小于5%)
对角矩阵存储:
定义:稀疏矩阵:设在mxn的矩阵中有个非零元素。令 δ = t / ( m x n ) δ=t/(mxn) δ=t/(mxn),当 δ ≤ 0.05 δ≤0.05 δ≤0.05时称为稀疏矩阵。
三元组存储: ( i , j , a i j ) (i,j,a_{ij}) (i,j,aij),行号,列号,数值
压缩存储原则:存各非零元的值、行列位置和矩阵的行列数。
三元组的不同表示方法可决定稀疏矩阵不同的压缩存储方法。
三元组顺序表又称有序的双下标法。
三元组顺序表的优点:非零元在表中按行序有序存储,因此便于进行依行顺序处理的矩阵运算。
三元组顺序表的缺点:不能随机存取若按行号存取某一行中的非零元,则需从头开始进行查找。
value | row | col |
---|---|---|
down | right |
例如:
广义表(又称列表 Lists)是 n ≥ 0 n≥0 n≥0个元素 a 0 , a 1 , ⋅ ⋅ ⋅ , a n − 1 a_0,a_1,···,a_{n-1} a0,a1,⋅⋅⋅,an−1的有限序列,其中每一个 a i a_i ai或者是原子,或者是一个广义表。
例子:
广义表与线性表的区别
广义表可以看成是线性表的推广,线性表是义表的特例。
广义表的结构相当灵活,在某种前提下,它以兼容线性表、数组、树和有向图等各种常用的数据结构
当二维数组的每行(或每列)作为子表处理时,二维数组即为一个广义表。
另外,树和有向图也可以用广义表来表示。
由于广义表不仅集中了线性表、数组、树和有向图等常见数据结构的特点,而且可有效地利用存储空间,因此在算机的许多应用领域都有成功使用广义表的实例。
广义表的基本运算
(1)求表头 GetHead((L):非空广义表的第一个元素,可以是一个元素,也可以是一个子表。
(2)求表尾 GetTail((L):非空广义表除去表头素以外其它元素所构成的表。表尾一定是一个表。
例:
D = ( E , F ) = ( a , ( b , c ) , F ) D=(E,F)=(a,(b,c),F) D=(E,F)=(a,(b,c),F)
G e t H e a d ( D ) = E GetHead(D)=E GetHead(D)=E G e t T a i l ( D ) = ( F ) GetTail(D)=(F) GetTail(D)=(F)
G e t H e a d ( E ) = a GetHead(E)=a GetHead(E)=a G e t T a i l ( E ) = ( ( b , c ) ) GetTail(E)=((b,c)) GetTail(E)=((b,c))
G e t H e a d ( ( ( b , c ) ) ) = ( b , c ) GetHead(((b,c)))=(b,c) GetHead(((b,c)))=(b,c) G e t T a i l ( ( ( b , c ) ) ) = ( ) GetTail(((b,c)))=() GetTail(((b,c)))=()
G e t H e a d ( ( b , c ) ) = b GetHead((b,c))=b GetHead((b,c))=b G e t T a i l ( ( b , c ) ) = ( c ) GetTail((b,c))=(c) GetTail((b,c))=(c)
G e t H e a d ( ( c ) ) = c GetHead((c))=c GetHead((c))=c G e t T a i l ( ( c ) ) = ( ) GetTail((c))=() GetTail((c))=()
案例4.1 病毒感染检测
因为病毒是环状的,解决办法–滑动窗口