一、线性结构
1、线性表
|------|------|--------------|--------------|
| 性能类别 | 具体项目 | 顺序存储 | 链式存储 |
| 空间性能 | 存储密度 | =1 | |
| 空间性能 | 容量分配 | 静态分配 | 动态分配 |
| 时间性能 | 查找运算 | O(n) | O(n) |
| 时间性能 | 读运算 | O(1) | O(1) ~ O(n) |
| 时间性能 | 插入运算 | O(1) ~ O(n) | O(1) |
| 时间性能 | 删除运算 | O(n) | O(1) |
(1):顺序表
查询、修改快,新增、删除慢(因为新增、删除需要修改元素下标,读数据是有序的)
)1:存储方式
顺序存储方式:数组的内存是连续、静态分配的,即在使用数组之前需要分配固定大小的内存空间
|---|---|---|---|---|---|---|---|
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
)2:操作次数公式
读操作(读指定下标值):直接读下标
查询操作(查找值):比较元素进行查询,最少1次,最多n次,平均次数公式:(n + 1) / 2(n表示元素个数)
插入操作:将插入新元素位置之后的所有元素位置后移,平均次数公式:(n + 1) / 2(n表示元素个数)
删除操作:将删除的元素位置之后的所有元素位置前移,平均次数公式:(n - 1) / 2(n表示元素个数)
(2):链表
查询、修改慢,新增、删除快(因为读只能从head开始读,增、删只需要修改指向即可)
)1:存储方式
链表存储方式:链表的内存是不连续的,前一个元素存储地址的下一个地址中存储的不一定是下一个元素。链表通过一个指向下一个元素地址的引用将链表中的所有元素串起来

)2:概念
>尾节点:最后一个有效节点
>首节点:第一个有效节点
>头节点:第一个有效节点之前的那个节点,存放链表首地址
>头指针:指向头结点的指针变量
>尾指针:指向尾节点的指针变量
)3:分类
1.单向链表

特点:
>n个节点离散分布,彼此通过指针相联系
>除头结点和尾节点外,每个节点都只有一个前驱节点和一个后继节点。头结点没有前驱节点,尾节点没有后继节点
>头节点不存放有效数据,只存放链表首地址。其头结点的数据类型和其他节点的数据类型相同
>加头结点的目的是方便对链表的操作,比如在链表头部进行节点删除、插入
2.双向链表

特点:双向指向,前驱+后继
3.循环链表

特点:从任意节点都能找到头结点,从而重新遍历
)4:基本操作
1.单链表
>删除:将待删除节点的前驱节点指针指向后继节点
第一步:P.data = P.link.data(将P数值改为下一节点Q的数值)
第二步:Q = P.link(待删除指针)
第三步:P.link = P.link.link(Q.link)
第四步:free(Q)(释放Q指针)

>新增:先将新增节点指针指向前驱节点的指针指向,再将前驱节点的指针指向指向新增节点自身
第一步:S.link = P.link
第二步:P.link = S

2.双向链表
>删除
第一步:P.front.next = P.next
第二步:P.next.front = P.front
第三步:free(P)

>新增
第一步:P.front = L
第二步:P.next = L.next
第三步:L.next.front = P
第四步:L.next = P

2、队列与栈
(1):队列
先进先出:入队序列与出队序列必然相同
1.常规

2.循环队列
队空条件:头指针和尾指针指向同一节点 head = tail
队满条件:队尾+1%容量取余=队头 (tail+1)%size=head
队列长度:(队尾-队头+容量)%容量取余 (tail-head+size)%size=长度
(2):栈(灵活序列)
1.常规

(3):例题

已知:通用:入队序列与出队序列必然相同,题示:先出栈再入队列,出栈与入队相同
所以得出结论:出队列与出栈序列相同

已知:循环链表不需要遍历,所以入队和出队都不需要遍历

不破坏顺序(合法)的有四种
a,b,c,e,d
a,b,e,c,d
a,e,b,c,d
e,a,b,c,d

ab进入,cd进入
b不出,则a出不来,所以第一种A的顺序是不可能
3、串
串是仅由字符构成的有限序列,是一种线性表
(1):基本概念
)1.概念
1.空串:长度为0,不包含任何字符
2.空格串:由一个或多个空格组成的串
3.子串:由串中任意长度的连续字符构成的序列:如字符串ABC,子串有A,B,C,AB,BC,及空串,计算子串数:2n-1,n表示串长度
4.子序列:将串中一些字符提取出来得到新串,并且不改变他们的相对位置,不必连续:如字符串ABC,子序列有A,B,C,AB,AC,BC,ABC,及空串,计算子序列数:2^n,n表示串长度
5.串比较:两串比较,实际比较的是ASCII码值
6.串相等:两串长度相等且对应序号的字符也相等
7.非平凡子串:非空且不同于串自身(串中包含的字符不在串当中,设串为a,非空且不是自身,不会有这种情况),这种情况不会存在,所以个数为0,计算数(n+1)(n-1)/2
)2.操作
1.StrAssign(s, t):串赋值
2.Concat(s, t):串拼接
3.StrLength(s):求串长度
4.StrCompare(s, t):串比较,-1表示s < t,0表示s = t,1表示s > t
5.SubString(s, start, len):求子串,s从第start下标开始,截取len长的子串
)3.存储
1.顺序存储(数组)
2.链式存储
(2):模式匹配
子串的定位操作通常称为串的模式匹配
1.朴素的模式匹配算法(布鲁特-福斯算法):子串匹配主串,每个字符逐个匹配,匹配失败,子串回到下标`起始位置继续匹配,主串下标移至当前下标的下一个位置。若字符串较长,则非常耗时
2.改进的模式匹配算法(KMP算法):依据模式串的next函数值实现子串滑动。若:令nextj=k,则nextj表示当前模式串的Pj与主串中相应字符不相等时,令模式串的Pnextj与主串的相应字符进行比较(j=nextj)

设:匹配串是abaac
next数组长度与匹配串长度相等,则next数组长度也是5
|-------|---|---|---|---|---|
| 位序 | 1 | 2 | 3 | 4 | 5 |
| 模式串 | a | b | a | a | c |
| next值 | | | | | |
求:
>next1 = 0:根据公式,j=1时返回0
>next2 = 1:根据公式,取最大k,k介于1与j之间,已知j=2,1与2之间没有实际值,所以返回其他情况,即1
next值的前两位是0和1,代码是这样初始化的,记住就行了
|-------|---|---|---|---|---|
| 位序 | 1 | 2 | 3 | 4 | 5 |
| 模式串 | a | b | a | a | c |
| next值 | 0 | 1 | | | |
>next3 = 1:计算next第3位,即next3的值
|-------|---|---|----------|---|---|
| 位序 | 1 | 2 | 3 | 4 | 5 |
| 模式串 | a | b | a | a | c |
| next值 | 0 | 1 | 当前计算结果=1 | | |
比较基准:用前一位的模式串进行比较,记作模式串2,模式串2 = b, 即比较基准为'b'。
比较对象:与什么比较呢,前一位next值所对应的位序上的字符进行比较,因为next2 = 1,所以与位序1上的字符即模式串1 = a比较。将b与a进行比较。
计算结果:如果不相等,结果为1;如果相等,在前一位next值上+1。比较到模式串第一个字符为止。这里已经比较到第一个模式串字符了,而且b!=a,所以结果为1.
>next4 = 2:计算next第4位,即next4的值
|-------|---|---|---|----------|---|
| 位序 | 1 | 2 | 3 | 4 | 5 |
| 模式串 | a | b | a | a | c |
| next值 | 0 | 1 | 1 | 当前计算结果=2 | |
比较基准:用前一位的模式串进行比较,即模式串3 = a, 即比较基准为'a'。
比较对象:与什么比较呢,前一位next值所对应的位序上的字符进行比较,即与next3 = 1位序上的字符比较,即模式串1 = a。将a与a进行比较。
计算结果:如果不相等,结果为1;如果相等,在前一位next值+1。比较到模式串第一个字符为止。这里已经比较到第一个模式串字符了,而且a=a,所以结果为next3+1 = 1+1 = 2.
>next5 = 2:计算next第5位,即next5的值
|-------|---|---|---|---|----------|
| 位序 | 1 | 2 | 3 | 4 | 5 |
| 模式串 | a | b | a | a | c |
| next值 | 0 | 1 | 1 | 2 | 当前计算结果=2 |
比较基准:用前一位的模式串进行比较,即模式串4 = a, 即比较基准为'a'。
比较对象:与前一位next值所对应的位序上的字符进行比较,即与next4 = 2位序上的字符比较,即模式串2 = b。将a与b进行比较,不相等,当前结果初始化为1。因为没有比较到第1位的字符串,接着比较:与位序为next2 = 1的字符比较,即模式串1=a。将a与a比较,相等,当前结果+1,即结果为1+1 = 2. 因为已经比较到第一位字符串了,所以比较结束。
最终,next值为01122.
就是next的最开始两位为01.接下来每一位的值,都是用前面的一位模式串值去比较,一直比较到模式串的第一位为止。如果相等,当前结果为前一位的next值+1,如果不等,则初始化为1.
二、数组与矩阵
1、数组
1.一维数组an:ai的存储地址计算为 a+i*len,a为起始地址,i为下标,len表示元素长度
2.二维数组amn:aij存储地址计算为:行、a+(i*n+j)*len,列、a+(j*m+i)*len,m表示行,n表示列,len表示元素长度,其中(i*n+j)和(j*m+i)为偏移量
当i和j相同时,偏移量也相同
设:五行五列的二维数组a中,每个元素占2个字节,求元素a23的行位置与列位置
解:套入公式
行:a+(i*n+j)*len = a+(2*5+3)*2B = a+26B
列:a+(j*m+i)*len = a+(3*5+2)*2B = a+34B
2、矩阵
(1):稀疏矩阵
1.上三角矩阵:对应一维数组下标计算公式:(2n-i+1)*i/2+j,i表示行,j表示列,n表示列长度
aij,上三角i

2.下三角矩阵:对应一维数组下标计算公式:(i+1)*i/2+j,i表示行,j表示列,n表示列长度
aij,下三角i>=j

3.对角矩阵:对应一维数组下标计算公式:2i+j-2,i表示行,j表示列,n表示列长度
aij,上三角i=j

设:对角矩形A如图,转换为数组,起始下标从0开始,则下标k与i、j的对应关系是(A:k=2i+j-2)
A:k=2i+j-2
B:k=2i-j+2
C:k=3i+j-1
D:k=3i-j+2
解:思路,套入实例
根据图转为一维数组求得:a1,1 = 数组1,a1,2 = 数组2,a2,1 = 数组3,a2,2 = 数组4,···
根据实例(a1,1 = 数组1)设:k=1,
A:k=2i+j-2 = 2*1+1-2=1
B:k=2i-j+2 = 2*1-1+2=3(非1)
C:k=3i+j-1 = 3*1+1-1=3(非1)
D:k=3i-j+2 = 3*1-1+2=4(非1)
