第一章 绪论
1.1数据结构三要素
数据的逻辑结构、数据的存储结构、数据的运算。
1.2算法的特性
①有穷性;②确定性;③可行性;④输入;⑤输出
1.3时间复杂度
一个语句的频度是指该语句在算法中被重复执行的次数,算法中所有语句频度之和记为T(n),它是算法问题规模n的函数,T(n)=O(f(n))。
(1)加法原则
(2)乘法原则
(3)常见的渐近时间复杂度
1.4空间复杂度
算法原地工作是指算法所需的辅助空间为常量,即O(1)。
第二章 线性表
2.1线性表
2.1.1定义
线性表是具有相同数据类型的n个数据元素的有限序列,一般表示为
L=(a1, a2,… ai, ai+1,…, an), a1称表头元素,an称表尾元素。除第一个元素外,每个元素有且仅有一个直接前驱,除最后一个元素外,每个元素有且仅有一个直接后继。
2.1.2基本操作
2.2线性表的顺序表示
2.2.1顺序表的定义
线性表的顺序存储又称顺序表,它是用一组地址连续的存储单元依次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也相邻。
线性表中元素的位序是从1开始的,而数组中元素的下标是从0开始的。
2.2.2线性表的顺序存储类型描述
①静态存储
②动态存储
不需要为线性表一次性划分所有空间。
动态分配语句如下。
2.2.3顺序表基本操作
①插入
注:此次线性表的位序从0开始。
②删除
删除顺序表L中第i(1≤i≤L.length)个位置的元素,用引用变量e返回。若i的输入不合法,
③按值查找
2.3线性表的链式表示(单链表)
2.3.1单链表的定义
线性表的链式存储又称单链表,它是指通过一组任意的存储单元来存储线性表中的数据元素,对每个链表结点,包含一个数据域(data:存放数据元素),一个指针域(next:存放其后继结点的指针)。
2.3.2线性表的链式存储类型描述(单链表中结点类型描述)
强调一个单链表:使用LinkList
强调一个结点:使用Lnode
2.3.3主要特点
①带头结点、不带头结点
带头结点单链表:在单链表第一个结点之前附加一个结点,称为头结点,头结点的数据域可以不设任何信息。
②空表判断
带头结点(推荐使用):L->next==NULL
不带头结点:L ==NULL
③遍历单链表
查找某个特定的结点时,需要从表头开始遍历,依次查找。
2.3.4单链表基本操作
①采用头插法建立单链表
从一个空表开始,生成新结点,并将读取到的数据存放到新结点的数据域中,新结点插入到当前链表的表头,即头结点之后。头插法可将插入元素进行逆置。
②采用尾插法建立单链表
该方法将新结点插入到当前链表的表尾,为此必须增加一个尾指针r,使其始终指向当前链表的尾结点。元素顺序与插入先后顺序一致。
③按序号查找表结点
④按值查找表结点
⑤插入结点
⑥删除结点
2.4双链表
2.4.1双链表基本定义
双链表结点中有两个指针prior和next,分别指向其前驱结点和后继结点。解决单链表只能从头结点依次顺序向后遍历。
2.4.2双链表存储结构类型描述(双链表中结点类型描述)
2.4.3主要特点
判空条件:P->prior==L
2.4.4基本操作
双链表的按值查找和按位查找操作与单链表相同。
①双链表插入操作
上述代码的语句顺序不是唯一的,但也不是任意的,①和②两步必须在④不之前,否则*P的后继结点的指针就会丢掉。
②双链表删除操作
2.5循环单链表
2.5.1循环单链表定义
与单链表的区别在于,表中最后一个结点的指针不是NULL,而改为指向头结点,从而整个链表形成一个环。表尾结点*r的next域指向L,故表中没有指针域为NULL的结点
2.5.2主要特点
判空条件:L->prior==L
2.6循环双链表
2.6.1循环双链表定义
每个结点有两个指针,分别是prior和next,头结点的prior指针需指向尾结点,尾结点的next指针需指向头结点。
2.6.2主要特点
判空条件:L->prior==r->next==L
第三章 栈
3.1栈的定义
栈是只允许在一端进行插入或删除操作的线性表(后进先出)。
栈顶(Top):允许进行插入删除的那一端
栈底(Bottom):固定的,不允许进行插入删除的另一端
n个不同元素进栈,出栈元素不同的排列的个数为Cn2n/(n+1)。
3.2栈的基本操作
3.3栈的顺序存储结构描述
3.4顺序栈主要特点
①栈顶指针:初始时设置S.top = -1
②栈空条件:S.top == -1
③栈满条件:S.top == MaxSize-1(从序号0开始存储,所以最后一个元素序号-1)
④栈长:S.top+1
进栈操作:栈不满时,栈顶指针先加1,再送值到栈顶元素;
出栈操作:栈非空时,先取栈顶元素值,再将栈顶指针减1;
3.5顺序栈常用的基本运算
3.6栈的链式存储结构
便于多个栈共享存储空间和提高其效率,且不存在栈满上溢的情况。通常采用单链表实现,并规定所有操作都是在单链表的表头进行的。这里规定链栈没有头结点,Lhead指向栈顶指针。
栈的链式存储类型描述
3.7共享栈
利用栈底位置对不变的特性,可让两个顺序栈共享一个一维数组空间,将两个栈的栈底分别设置在共享空间的两端,两个栈顶向共享空间的中间延伸。
0号栈:栈顶指针top0=-1时为空;进栈时先加1再赋值,出栈时先取值再减1。
1号栈:栈顶指针top1=MaxSize时为空;进栈时先减1再赋值,出栈时先取值加1。
栈满条件:top1- top0==1
当初始时,栈顶指针top0=0,top1=MaxSize-1时,进栈出栈与上述正好相反,栈满条件为top0- top1==1
第四章 队列
4.1队列的定义
只允许在表的一端进行插入,而在表的另一端进行删除的操作受限线性表(先进先出)。
队头(Front):允许删除的一端
队尾(Rear):允许插入的一端
4.2队列的常用操作
4.3队列的顺序存储描述
分配一块连续的存储单元存放队列中的元素,并附设两个指针,队头指针front指向队头元素,队尾指针rear指向队尾元素的下一个位置(具体问题具体分析)。
4.4顺序队列主要特点
①初始状态:Q.front=Q.rear=0
②队空条件:Q.front==Q.rear==0
③进队操作:队不满时,先送值到队尾元素,再将队尾指针加1
④出队操作:队不空时,先取队头元素值,再将队头指针加1
4.5循环队列(重点)
将顺序队列臆造为一个环状的空间,即把存储队列元素的表从逻辑上视为一个环。当队头指针Q.front=MaxSize-1后,在前进一个位置就自动到0,可利用除法取余运算(%)来实现。
①初始状态:Q.front=Q.rear=0
②队空条件:Q.front==Q.rear
③队列长度:(Q.rear- Q.front+ MaxSize)% MaxSize
④队头指针加1:Q.front=(Q.front+ 1)% MaxSize
⑤队尾指针加1:Q. rear =(Q. rear + 1)% MaxSize
区分队空、队满,主要有三种方式:
①牺牲一个单元,约定“队头指针在队尾指针的下一个位置作为队满标志” | ②增设表示元素个数的数据成员 | ③增设Tag数据成员,区分队满还是队空 | |
---|---|---|---|
队空条件 | (Q. rear + 1)% MaxSize== Q.front | Q.size==0 | tag=0时,若因删除导致Q.front==Q.rear |
队满条件 | Q.front=Q.rear | Q.size==MaxSize | tag=1时,若因插入导致Q.front==Q.rear |
4.6循环队列常用操作
4.7链式队列
链式队列实际上是一个同时带有队头指针和队尾指针的单链表,头指针指向队头结点,尾指针指向尾结点。
链式队列存储类型描述
4.8链式队列常用操作
4.9双端队列
双端队列:是指允许两端都可以进行入队和出队操作的队列。
输出受限的双端队列,是指允许一端进行插入和删除,但在另一端只允许插入;输入受限的双端队列,是指允许一端进行插入和删除,但在另一端只允许删除。
第五章 数组和矩阵
5.1数组的定义
数组是由n个相同类型的数据元素构成的有限序列,每个数据元素称为一个数组元素,每个元素在n个线性关系中的序号称为该元素的下标。
5.2数组的存储结构
以以为数组A[0…n-1]为例,其存储结构关系为:
LOC(ai)=LOC(a0)+i×L(0≤i≤n,L是每个数组元素所占的存储单元)
对于二维数组有两种映射方式,按行优先和按列优先。按行优先存储的基本思想是:先行后列,先存储行号较小的元素,行号相等先存储列号较小的元素。
LOC(ai,j)=LOC(a0,0)+〔i*每行元素个数+j〕 注:起始元素下标从0开始
LOC(ai,j)=LOC(a1,1)+ 〔(i-1)*每行元素个数+j-1)〕 注:下标从1开始
5.3对称矩阵
n阶方阵A[1..n] [1..n]中,任意一个元素aij = aji(0≤i,j≤n),此矩阵存放在一维数组B[n(n+1)/2]。
5.4三角矩阵
下三角矩阵:上三角区的所有元素均为同一常量,存储完下三角区和主对角线上的元素之后,紧接着存储对角线上方的常量一次,故此矩阵可存放在一维数组B[n(n+1)/2+1]中。
上三角矩阵:下三角区的所有元素均为同一常量,同上。
5.5三对角矩阵(带状矩阵)
所有非零元素都集中在以主对角线中心的3条对角线的区域,其他区域元素都为零。
5.6稀疏矩阵
矩阵中非零元素个数相对比较少,采取三元组(行标、列标、值)结构存储,三元组即可采用数组存储或十字链表法存储。
第六章 串
6.1串的定义
串是由零个或多个字符组成的有限序列,一般记为S=‘a1a2…an’(n≥0),ai可以是字母、数字或其他字符。
6.2串的存储结构
①定长顺序存储表示
类似于线性表的顺序存储结构,用一组地址连续的存储单元存储串值的字符序列。
②堆分配存储表示
仍然以一组地址连续的存储单元存放串值的字符序列,但它们的存储空间是在程序执行过程中动态分配得到的。并用malloc()和free()函数来完成动态存储管理。
③块链存储表示
类似于线性表的链式存储结构。
6.3串的基本操作
①StrCompare
②SubString
③Index
6.4简单的模式匹配算法
将主串中与模式串长度相同的子串搞出来,挨个与模式串对比,当子串与模式串某个对应字符不匹配时,就立即放弃当前子串,转而检索下一个子串(此次采用定长顺序存储结构)。主串指针会出现回溯现象。最坏时间复杂度为O(mn)。
6.5 KMP模式匹配算法
首先了解以下几个概念:
字符串前缀:指除最后一个字符以外,字符串的所有头部子串;
字符串后缀:指除第一个字符以外,字符串的所有尾部子串;
部分匹配值:指字符串的前缀和后缀的最长相等前后缀长度。
下面以‘ababa’为例进行说明:
‘a’:前缀、后缀都为空集,最长相等前后缀长度为0;
KMP算法基本思想:当第j个字符匹配失败,由前1~j-1个字符组成的串记为S,则:next[j]=S的最长相等前后缀长度+1,特别的next[1]=0,next[2]=1。若next[1]=-1,则整体都减1。最坏时间复杂度为O(m+n)
例:模式串‘ababaa’
序号j | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|
S | a | b | a | b | a | a |
next[j] | 0 | 1 | 1 | 2 | 3 | 4 |