字符串
-
串的定义
字符串(串):零个或多个字符组成的有限序列S=“a1,a2…an”(n>=0)
S为串名,n为串的长度, “ 为定界符, 字符序列为串值。 -
串的基本概念
空串:是指长度=0的串,它不包含任何字符。
空格串:是仅由一个或多个空格组成的串,长度大于等于1。
子串:串中任意个连续的字符组成的子序列。
主串:包含子串的串相应地称为主串。
位置:字符在序列中的序号。子串在主串中的位置则以子串的第一个字符在主串中的位置来表示。
相等:两个串的长度相等,并且对应位置的字符都相等。 -
抽象数据类型定义
ADT String
DataModel
串中的数据元素仅由一个字符组成,相邻元素具有前驱和后继关系
Operation
StrAssign:串赋值
StrLength:求串S的长度
Strcat:串连接
StrSub:求子串
StrCmp:串比较
StrIndex:子串定位
StrInsert:串插入
StrDelete:串删除
endADT -
串的存储
字符串通常采用顺序存储,即用数组存储(定长顺序串)
堆串
块链串 -
串的基本操作
C/C++语言提供了很多关于字符串操作的库函数,如strcpy函数、strncpy函数、strlen函数、strcmp函数、strcat函数等。除此之外,C++语言也有STL模板类string来操作字符串。 -
串的模式匹配
- BF算法(暴力匹配算法)
int Index(SString S,int pos,SString T){
int i=pos,j=1;
while (i<=S.len &&j<=T.len)
if (S.ch[i]=T.ch[jl)
{
++i
++j
}
else{
i=i-j+2;
j=1
}
if (j>T.len)
return i-T.len;
else
return 0;
}
O(m*n)
-
- KMP算法
class Solution {
public:
int strStr(string s, string p) {
int n = s.size(), m = p.size();
if(m == 0) return 0;
//设置哨兵
s.insert(s.begin(),' ');
p.insert(p.begin(),' ');
vector<int> next(m + 1);
//预处理next数组
for(int i = 2, j = 0; i <= m; i++){
while(j and p[i] != p[j + 1]) j = next[j];
if(p[i] == p[j + 1]) j++;
next[i] = j;
}
//匹配过程
for(int i = 1, j = 0; i <= n; i++){
while(j and s[i] != p[j + 1]) j = next[j];
if(s[i] == p[j + 1]) j++;
if(j == m) return i - m;
}
return -1;
}
};
O(m+n)
多维数组
数组的定义
数组:由一组类型相同的数据元素构成的有序集合,每个数据元素称为一个数组元素(简称为元素),每个元素受 n(n≥1)个线性关系的约束,每个元素在 n 个线性关系中的序号i1、i2、…、in 称为该元素的下标,并称该数组为 n 维数组
数组的特点
(1)元素本身可以具有某种结构,属于同一数据类型;
(2)数组是一个具有固定格式和数量的数据集合。
数组的基本操作
(1)存取:给定一组下标,读出对应的数组元素
(2)修改:给定一组下标,存储或修改与其相对应的数组元素
ADT Matrix
DataModel
相同类型的数据元素的有序集合,每个元素受n(n≥1)个线性关系的约束
Operation
InitMatrix:数组的初始化
DestroyMatrix:数组的销毁
GetMatrix:读操作,读取这组下标对应的数组元素
SetMatrix:写操作,存储或修改这组下标对应的数组元素
endADT
数组的存储结构
数组没有插入和删除操作,所以,不用预留空间,适合采用顺序存储
- 按行优先:先存储行号较小的元素,行号相同者先存储列号较小的元素
- aij前面的元素个数=整行数×每行元素个数+本行中aij前面的元素个数=(i -l1)×(h2-l2+1)+(j -l2)
- 按列优先:先存储列号较小的元素,列号相同者先存储行号较小的元素
- 数组在内存中以一维数组存储
特殊矩阵的压缩存储
-
特殊矩阵:
矩阵中很多值相同的元素并且它们的分布有一定的规律 -
特殊矩阵如何压缩存储
为值相同的元素分配一个存储空间 -
特殊矩阵压缩存储的要求
保证随机存取,即在O(1)时间内寻址 -
对称矩阵的压缩存储
- aij 在一维数组中的序号= i×(i-1)/2+ j
∵一维数组下标从 0 开始
∴aij 在一维数组中的下标k = i×(i-1)/2+ j-1 - 对称矩阵压缩存储后的寻址方法
对于下三角中的元素aij(i ≥ j):k=i×(i-1)/2+j -1
对于上三角中的元素aij(i<j),因为aij=aji,则 k=j×(j-1)/2+i -1
- aij 在一维数组中的序号= i×(i-1)/2+ j
-
三角矩阵的压缩存储
下三角矩阵压缩存储后的寻址方法
对于下三角中的元素aij(i ≥ j):k=i×(i -1)/2 + j-1
对于上三角中的元素aij(i<j):k=n×(n + 1)/2 -
对角矩阵的压缩存储
对角矩阵:所有非零元素都集中在以主对角线为中心的带状区域中,所有其他元素都为零
元素 aij 在一维数组中的序号=2 + 3(i-2)+( j-i + 2)=2i + j-2
∵一维数组下标从 0 开始
∴元素 aij 在一维数组中的下标= 2i + j-3
稀疏矩阵的压缩存储
- 稀疏矩阵:矩阵中有很多零元素,并且分布没有规律
- 稀疏矩阵如何压缩存储?
只存储非零元素,零元素不分配存储空间 - 如何只存储非零元素?
三元组:(行号,列号,非零元素值)
三元组
- 三元组:(行号,列号,非零元素值)
template <typename DataType>
struct element
{
int row, col;
DataType item
};
- 三元组表:将稀疏矩阵的非零元素对应的三元组所构成的集合,按行优先的顺序排列成一个线性表
((1, 1, 3), (1, 4, 7), (2, 3, 1), (3, 1, 2), (5, 4, 8)) - 三元组顺序表:采用顺序存储结构存储三元组表
const int MaxTerm = 100;
struct SparseMatrix
{
element data[MaxTerm];
int mu, nu, tu;
};
- 三元组顺序表不适合什么情况?
稀疏矩阵的加法、乘法等操作,非零元素的个数及位置都会发生变化,则在三元组顺序表中就要进行插入和删除操作,顺序存储就十分不便 - 三元组顺序表的矩阵转置
2.快速转置一基本策略
转置前矩阵
十字链表
十字链表:采用链接存储结构存储三元组表
- 数据类型定义
typedef struct OLNode
{
int row,col;//行、列号
ElemType value;
struct OLNode*right,*down;//行、列指针
}OLNode,*OLink;
typedef struct
{
OLink*row_head,*col head;/行列链表头指针数组
int m,n;
}CrossList;