章节大纲

一、线性结构
1、线性表
1、1 线性表的定义
定义:
最基本的数据结构,一个线性表是由n(n ≥ 0)个元素的有限集合,表示(a1,a2...an)

特点:
1、存在唯一的一个称作"第一个"的元素(第一个元素)
2、存在唯一的一个称作"最后一个"的元素(最后一个元素)
3、除第一个元素外,序列中每一个元素都有一个"直接前驱"
4、除最后一个元素外,序列中每一个元素都有一个"直接后继"
比如:A → B → C → D
B 的直接前驱:A
B 的直接后继:C
单向链表只能直接访问后继;双向链表同时直接访问前驱、后继
1、2 线性表的存储结构(顺序+链式)

总结:读取、查找方便;插入和删除需要移动数据 (逻辑上相邻、物理上相邻)
数据域:具体数值
指针域:用来存储数据和数据之间的关系,同样占用空间

总结:插入、删除方便;随机访问难(逻辑上相邻、物理上不一定相邻,需要存储指针)
1、3 时间复杂度对比
时间复杂度的定义:程序执行次数与数据总量之间的关系
O(1):常数阶:无论数据量多大,我需要的次数都是固定的,不会循环。
O(n):线性阶:数据量翻倍,耗时也翻倍,一般都需要通过循环实现
1、4 单链表、双链表,以及对应循环单/双链表的区别

想省空间? → 单链表。
经常要在"当前节点"的前面搞事情(插/删)? → 双链表。
需要从任意节点出发都能遍历全表? → 循环链表。
既要随便遍历,又要快速找前驱,还要快速找首尾? → 循环双链表(全能王,但费空间)
单链表的删除案例:

2、栈

📝 栈就不多说了,核心四个字:"后进先出"或者先进后出
根据输入序列来推导输出序列

2、1 栈的应用
1、递归:通常需要通过栈保存每一层的函数变量和返回值,通常在循环中比较容易遇到的就是栈溢出错误。
2、表达式求值
3、括号匹配
3、队列
定义: 一种"先进先出"的线性表,在队列中允许插入元素的一端称为队尾``,允许``删除元素的一端称为```队头``---->队尾进去、队头出来(先进先出)

3、1 循环队列
队尾:增加元素
队头:删除元素


3、2 判空与判满
判空: front == rear,头指针和尾指针相重叠。
判满: 牺牲一个存储单元,如果不牺牲就无法判断了,因为和判空会重复。
3、3 双端队列:要求进出队列必须要在同一端口

双端队列是一种允许在两端(队首、队尾)同时进行插入、删除操作的线性数据结构。
普通队列:只能队尾入、队首出(FIFO)
栈:只能同一端入、出(LIFO)
双端队列分类:
1、受限双端队列
输入受限双端队列:只能一端插入,两端删除
输出受限双端队列:只能一端删除,两端插入
2、不受限双端队列(标准 Deque):两端均可插入、删除
3.3 队列常见应用场景
广度优先搜索(BFS)
缓冲区(Buffer)
操作系统调度(先来先服务FCFS
4、串

4、1 空串
定义: 长度为0的串。
符号: () 或 ""。
特点: 啥都没有。
考点: 空串是任意串的子串。
注意要区别空格串,空格串的长度不为0,只是内容为空格,但实际还是没有什么意义
4.2 子串
定义: 主串中任意长度的连续字符序列。
特点: 连续!
二、非线性结构
1、数组(一维+二维)

数据元素数目固定。
数据元素具有相同的类型。
数据元素的下标具有上下界约束且下标有序。
2、矩阵

3、广义表

4、 树
树是n个(n >= 0)节点的有限集合,有且仅有一个根节点,当n = 0 时称为空树

4.1 树的基本概念
普通树、二叉树、满二叉树、完全二叉树

双亲、孩子和兄弟:子节点就是一个节点的子树,双亲节点(一般叫父节点)是子树的根节点,兄弟节点就是平级的节点。
节点的度: 一个节点拥有子树(子节点)的个数称为该节点的度。比如图中A的度就是3。
树的度: 树中所有节点度的最大值。
叶子结点: 度为0的节点,没有任何子节点。
内部节点: 排除叶子结点和根节点,其余都是内部节点。
节点的层次: 也就是层级,A是第一层,B、C、D是第二层,依此类推。
树的深度: 最大层数,也可以叫高度。
路径长度: 两个节点之间经过的边的数目。
有序 / 无序 树: 如果子树依次从左到右排序且不能变换位置就是有序树,反之则是无序树
4、2 二叉树
📝 二叉树和普通树的区别在于,二叉树的子树分为左子树和右子树,而普通树只有一颗子树


4、3 满二叉树和完全二叉树

4、4 二叉树的性质
4、5 二叉树的存储(顺序+链式)
1、顺序存储:
顺序存储方式完全二叉树是有优势的,因为节点都是满的,而一般二叉树还需要填充空节点,导致空间浪费

2、链式存储
一般分为二叉链表和三叉链表

---
4、6 二叉树的遍历(前序、中序、后序、层次)

4.7 最优二叉树(哈夫曼树)
定义:一种带权路径长度最短的二叉树

路径长度:从树根到每一个结点的路径长度之和。
带权路径长度 (WPL, Weighted Path Length):结点权值 × 结点到根的距离(层数-1)。
定义:WPL 最小的二叉树就是哈夫曼树
4.7 最优二叉树的构建
1、哈夫曼树构建

2、哈夫曼编码

思考:

4.8 树的存储结构

4.9 树和森林的遍历

4.10 树、森林、二叉树的相互转换

4.11 二叉排序树

4.12 平衡二叉树

5、 图
5、1 图的定义(边+顶点)

📝 图是由集合V和E 构成的二元组,记作G = ( V , E ),其中V是图中顶点的非空有限集合,E是图中边的非空有限集合


总结:

1、有向边:带箭头的单通道的边 A->B
2、无向边:不带箭头的双通道边 A-B
3、无向图:任意两点之间均为无向边
4、有向图:任意两点之间均为有向边
5、完全图:无向完全图+有向完全图
6、入度:进入顶点的边数为入度
7、出度:从顶点出去的边数为出度
8、无向图中没有入度和出度(不带箭头,无方向)
9、有向图中,顶点的度=出度+入度
10、路径:顶点到顶点之间的通道
5、2 图的存储结构(邻接矩阵+邻接表)
(1)邻接矩阵:

无向图:矩阵是对称的,第i ii行的所有元素之和 = 顶点i ii的度。(度就是有几根线)
有向图:不一定对称,出度看行,也就是看对应的顶点射出去了几根线。入度看列,看顶点被射中了几次。
优点: 查询很快,直接看矩阵对应的值即可,时间复杂度O ( 1 ) O(1)O(1)
缺点: 费空间
(2)邻接表:

优点:
节省空间: 有多少边就申请多少空间,适合稀疏图
计算出度快: 直接遍历对应节点的链表即可
缺点:
计算出度稍微慢一点,要遍历整个链表,不像矩阵直接计算和即可。
计算入度相当慢,需要把所有的链表遍历,除非维护一个逆向邻接表
5、3 图的遍历(深度+广度)
定义:从图中任意顶点出发,对图中所有顶点访问一次,且只访问一次
1、深度优先(DFS): 类似树的前序遍历

2、广度优先(BFS): 类似树的层次遍历

5、4 生成树和最小树



5、5 拓扑排序和关键路径


最短路径:


**总结:线性结构和非线性结构**
1、线性结构:元素之间存在一对一的前后次序关系,有唯一前驱、唯一后继(除首尾)
2、非线性结构:一对多 / 多对多,元素不存在简单的顺序一对一关系
判断技巧:能否排成一条直线序列
- 线性结构(常考)
满足:一对一
线性表(顺序表、链表)
栈(Stack)
队列(Queue)
串(字符串)
✅ 特点:广义表不一定是线性!只有全部元素都是原子、无嵌套的广义表才等价线性表;只要包含子表,广义表属于非线性
- 非线性结构(常考)
(1)树形结构:一对多
普通树
二叉树
二叉搜索树、平衡树、堆
哈夫曼树
(2)图形结构:多对多
有向图
无向图
网(带权图)
3、数据结构逻辑分类
线性结构
顺序表
链表(单链表、双向链表、循环链表)
栈
队列
串
非线性结构
树:普通树、二叉树、堆、哈夫曼树
图:有向图、无向图
集合
广义表