🌞欢迎来到数据结构的世界
🌈博客主页:卿云阁💌欢迎关注🎉点赞👍收藏⭐️留言📝
🌟本文由卿云阁原创!
🌠本阶段属于筑基阶段,希望各位仙友顺利完成突破
📆首发时间:🌹2021年2月16日🌹
✉️希望可以和大家一起完成进阶之路!
🙏作者水平很有限,如果发现错误,请留言轰炸哦!万分感谢!
目录
0️⃣✨✨✨串✨✨✨
串(string)(或字符串)是由零个或多个字符组成的有限序列,
一般记为: S="a1 a2 …… an" (n≥0)
模式匹配:求子串在主串中的起始位置称为子串定位或模式匹配。
ADT String{ 数据对象D:D={ai|ai∈ElemSet,i=1,2, …,n,n≥0} 数据关系R:R={<ai-1,ai>| ai-1,ai∈D,i=2,3, …,n } 基本操作P: 串赋值StrAssign(&S,chars):S是一个串变量,chars是一个串常量。将chars的值赋给串S; 串比较StrCompare(S,T):若串变量S>串变量T,则返回值>0;若S=T,则返回值为0;若S<T,则返回值<0; 求串长StrLength(S):返回S中元素的个数; 串联接Concat(&S,T1,T2):用S返回T1和T2联接而成的新串,如:T1="xyz",T2="abc",则Concat (&S,T1,T2)= "xyzabc",注意Concat (S,T1,T2)≠Concat (S,T2,T1); 求子串SubString(&T,S, pos, len):1≤pos≤StrLength(S),0≤len≤StrLength(S)-pos+1,用T返回S中的第pos个字符起长度为len的子串; 判断空串StrEmpty(S):若S为空串,则返回TRUE,否则返回FALSE; 串复制StrCopy(&T,S):将串S复制到串T; 串清空ClearString(S):将S置空串; 串定位Index(S,T,pos):串S和T存在,T是非空串,1≤pos≤StrLength(S),若T是S的子串,返回T在S中第一次出现的位置,否则返回0; 串置换Replace(&S,T,V):串S,T和V存在,T是非空串,用V替换主串S中出现的所有与T相等的不重叠的子串。例如:设S="bbabbabba",T="ab",V="a",则Replace(&S,T,V)的结果是S="bbababa"; 串插入StrInsert(&S,pos,T):1≤pos≤StrLength(S)+1,在串S的第pos个字符之前插入串T; 串删除StrDelete(&S,pos,len): 1≤pos≤StrLength(S)-len+1,从串S中删去第pos字符起长度为len的子串; 串销毁DestroyString(&S) :串S被销毁,并回收串空间; }ADT String
串的表示和实现
串的表示有三种方式:定长顺序串、堆串和链串
串的定长顺序存储表示
方法一
#define MAXSIZE 100 typedef struct { char ch[MAXSIZE];//字符数组存储串值 int length;//整型变量表示串的长度 }SString;
方法二
定义字符数组 s[MAXSIZE+1]; 用串数组的第一个单元s[0]存放串的实际长度,串值存放在s[1]~s[MAXSIZE]中,用字符'\0'作为串的结束符。这种方法字符的序号与存储位置是一致的。 数据类型描述如下:
#define MAXSIZE 100 //用户可在100以内定义最大串长 typedef char SString[MAXSIZE+1]; //0号单元存放串的实际长度
串的堆分配存储表示
typedef struct { char *ch; //若是非空串,则按串长分配存储区,否则ch为NULL int length; //串的实际长度 }HString;
串的链式存储结构
串的链式数据类型中结点大小为1的结点描述如下: typedef struct Node { char data; struct Node *next; }LinkString;
串的模式匹配算法
1. BF算法
将主串S的第一个字符和模式T的第1个字符比较,若相等,继续逐个比较后续字符;若不等,从主串S的下一字符起,重新与T第一个字符比较。直到主串S的一个连续子串字符序列与模式T相等。返回值为S中与T匹配的子序列第一个字符的序号,即匹配成功。否则,匹配失败,返回值0
int Index(SString S,SString T) { int i=1,j=1; while(i<=S[0]&&j<=T[0]) {if(S[i]==T[j]) { i++;j++; } //继续比较后继字符 else { i=i-j+2;j=1; } //指针后退重新开始匹配 } if (j>T[0]) return i-T[0]; else return 0; }
KMP算法
每当一趟匹配过程中出现字符比较不等时,不需回溯i指针,而是利用已经得到的“部分匹配”的结果将模式向右“滑动”尽可能远的一段距离后,继续进行比较。
本质在于j指针在下一次比较中回到哪一个位置。
2和3一样,1和2已经比较成功,所以1和3不需要比较。
a b c d
前缀:
a
a b
a b c
后缀
d
c d
b c d
1️⃣✨✨✨ 数组✨✨✨
1.一维数组
A[n]或A=( a0,al,…ai,…,an-1)。
2.二维数组
m行n列的二维数组 Amn可以表示为
矩阵的压缩存储
在数值分析过程中经常遇到一些比较特殊的矩阵,如对称矩阵、三角矩阵、带状矩阵和稀疏矩阵等。为了节省存储空间并且加快处理速度,下面讨论这些特殊矩阵的存储方法。
1.对称矩阵
对称矩阵是一个n阶方阵。其元素满足:aij=aji (0≤i,j≤n-1)。 对称矩阵中的元素是关于主对角线对称的,因此在存储时只存储上三角或下三角(包括对角线),使得对称的元素共享一个存储空间。这样,n阶矩阵中的n×n个元素就可以被压缩到 n(n+1)/2 个元素的存储空间中
以行优先顺序对面上的对称矩阵存储其下三角,存储序列为: 2,4,0,1,8,1,3,6,2,0,7,1,6,5,3
三角矩阵
⑴下三角矩阵 下三角矩阵与对称矩阵的压缩存储类似,不同之处在于存储完下三角中的元素以后,紧接着存储对角线上方的常量,因为是同一个常数,只需存储一个即可。数组下标与元素之间存在着如下对应关系:
⑵上三角矩阵 对于上三角矩阵,第一行存储n个元素,第二行存储n-1个元素,依次类推,aij的前面有i行,共存储n+(n-1)+…+(n-(i-1))=i(2n-i+1)/2个元素,在i行,aij前有j-i个元素,因此数组下标与元素之间存在着如下对应关系:
对角矩阵
A中第0行和第n-1行都只有两个非零元素,其余各行均为3个非零元素。对于不在第0行的非零元素aij,在它前面存储了矩阵的前i行元素,这些元素共2+3(i-1)个。若aij是本行中要存储的第1个非零元素,则k=2+3(i-1),此时,j=i-1,即k=2i+i-1=2i+j;若aij是本行中要存储的第2个非零元素,则k=2+3(i-1)+1=3i,此时,j=i,即k=2i+i=2i+j;若aij是本行中要存储的第3个非零元素,则k=2+3(i-1)+2=3i+1,此时,j=i+1,即k=2i+i+1=2i+j。因此,非零元素aij与数组b的下标之间存在着如下对应关系:k=2i+j。
稀疏矩阵
如果矩阵中有很多零元素,即零元素的个数远远大于非零元素的个数时,称该矩阵为稀疏矩阵。
有两种常用的存储稀疏矩阵的方法:三元组表示法和十字链表法。
三元组表示法
#define NUM 100 //矩阵中非零元素最大个数 typedef struct //三元组结构 { int r, c; //行号和列号 ElemType d; //元素值 }TupType; //三元组定义 typedef struct { int rows,cols,nums; //矩阵行数值、列数值、非零元素个数 TupType data[NUM]; //三元组表 }TSMatrix; //三元组表定义
2.十字链表
结点中三元组(i,j,v)表示非零元素所在的行、列和值,两个链域:行指针域(right)用来指向本行中下一个非零元素;列指针域(down)用来指向本列中下一个非零元素。 稀疏矩阵中同一列的所有非零元素通过down指针域链接成一个循环列链表,同一行的所有非零元素通过right指针域链接成一个带表头结点的循环行链表。因此,每个非零元素aij既是第i行循环链表中的一个结点,又是第j列循环链表中的一个结点,就像一个十字交叉路口,故称其为十字链表。
2️⃣✨✨✨ 广义表✨✨✨
广义表是n(n≥0)个元素a1,a2,a3,…,an的有限序列,
记作LS=(a1,a2,a3,…,an),
其中ai是LS的成员,可以是原子项,也可以是一个广义表(子表)。
LS是广义表的名字,n为它的长度。若ai是广义表,则称它为LS的子表
。当广义表LS非空时,称第一个元素a1为LS的表头(Head),称其余元素组成的表(a2,a3,…,an)是LS的表尾(Tail)。