线性数据结构
链表
std::list
是 STL 中的链表- 特点:是一条链,空间复杂度 \(O(n)\)
- 插入与删除十分方便,时间复杂度 \(O(1)\)
- 寻找与查询数据比较麻烦,时间复杂度 \(O(n)\)
- 数组大小固定,链表大小可动态调整
- 注意:
std::vector
不算数组,是数据结构
- 注意:
- 链表的分类
- 单向链表:每一个结点只存储下一个结点的指针
- (单/双向)循环链表:尾结点的指针指向首结点
- 双向链表:一个结点存储上下结点的指针(
prev
,next
)
- 判断插入元素指令是否正确:判断是否会有数据覆盖(模拟)
栈(stack, vector)
- 开一个口,先进后出
- 常用函数
- push() 压栈
- pop() 如果非空则弹栈
- top() 栈顶元素
- 可以用两个栈实现一个队列
- 给定入栈序列,判断出栈序列是否合法
- 草稿纸模拟一个栈,右边写进出栈序列
- 验证出栈队列中的元素是否能顺利弹出(如果能出立刻出)
- 给定出栈序列,判断入栈序列是否合法
队列(queue, deque)
- 开两个口,先进先出
- 常用函数
- push() 进队列
- pop() 出队列
- front() 首元素
- 双向队列 deque 可以实现栈
递推,递归
递归
- 在函数定义中使用函数本身的方法
- 思想是直接或间接地调用函数自身
- 递归利用堆栈解题
- 从未知信息一步步推向已知信息
递推
- 从已知信息一步步推向未知信息,找的是前后关系(递推式)
- 如斐波那契数列:\(f_n=f_{n-1}+f_{n-2}\)
简单图论
- 一些点用边连起来(可能是抽象概念)
- 边的方向
- 有向边:代表方向性
- 无向边:无方向性,相当于两条有向边
- 边的权值
- 带权图:边上带有边权
- 正权图:边权都为正数
- 图的分类
- 有向图
- 无向图
- 混合图
- 结点度数(无向图入度=出度)
- 入度:有向图有多少条边指向这一个结点
- 出度:有向图有
- 特殊情况
- 自环:结点的边指向自己
- 重边:两条相同的边
- 简单图:无重边、自环
- 连通图:无向图任意两点之间都相互可达
- 有向图强连通:无向图任意两点之间都相互可达,\(n\) 个结点,至少有 \(n\) 条边(一个环)
- 无向连通图如果 \(n\) 个结点,必须有 \(n-1\) 条边(一条链)
- 稠密图:一张图的边数接近点数的平方
- 稀疏图:边数远小于点数的平方,没有严格定义
- 完全图:任意不同两点间均有边(无向)/两条方向不同的边(有向)
- 图的存储
- 邻接矩阵:二维数组存边
e[u][v]
:u 连 v- 不带权:0/1
- 带权图:0/边权
- 邻接表
- 使用一个支持动态添加元素的数据结构构成的数组来存边,如
vector
- 使用一个支持动态添加元素的数据结构构成的数组来存边,如
- 邻接矩阵:二维数组存边
简单树
- 树:图里面没有环,并且是联通的
- 一般情况下,有环的图一定不是树
- 无根树制定一个结点为根,则为有根树
- 性质
- 边数 = 点数 - 1
- 任意两点之间仅有一条简单路径
- 任意不同两点间加边可以得到图中唯一一个环
- 概念及定义
- 父亲:从该结点到根结点的简单路径上的第二个结点
- 祖先:从该结点到根结点的简单路径上除它本身结点
- 子结点/后代:父亲结点反过来
- 结点深度:结点到根结点简单路径上的边数
- 高度:所有结点深度的最大值
- 子树:某个结点和它所有的后代和边组成的树
- 常见特殊树
- 链:与任意结点相连的边不超过两条的树
- 菊花:结点 u 与其他所有结点均相连(必须直接连)
- 二叉树:每个结点最多有两个子结点
二叉树
- 二叉树:每个节点最多只有两个儿子的有根树
- 完整二叉树:每个结点的子结点树一定为 0 或 2
- 完全二叉树:只有最下面两层节点度数可以小于 2,且最下面一层结点都集中在该层最左边的连续位置上
- 满二叉树/完美二叉树:所有叶节点深度相同的二叉树
- 前中后序遍历:根左右,左根右,左右根
- 序列反推:根据中序遍历序列和另外一个序列可以得出第三个序列(根据前序/有序遍历获得某子树的根节点,采用分治思想)
- 前序遍历伪代码
void 前序遍历(int x) {
输出:print 当前点编号
递归:前序遍历(左结点)
递归:前序遍历(右结点)
}
- 中序遍历伪代码
void 中序遍历(int x) {
递归:中序遍历(左结点)
输出:print 当前点编号
递归:中序遍历(右结点)
}
- 后序遍历伪代码
void 后序遍历(int x) {
递归:后序遍历(左结点)
递归:后序遍历(右结点)
输出:print 当前点编号
}
- 结点编号规律:结点 \(i\) 左儿子编号为 \(2i\),右儿子编号为 \(2i+1\)
- 哈夫曼树、哈夫曼算法、哈夫曼编码
搜索
- 深度优先搜索用栈
- 广度优先搜索用队列
排序
算法名称 | 最好时间复杂度 | 最坏时间复杂度 | 平均时间复杂度 | 是否稳定 |
---|---|---|---|---|
冒泡排序 | \(O(n)\) | \(O(n^2)\) | \(O(n^2)\) | 是 |
选择排序 | \(O(n^2)\) | \(O(n^2)\) | \(O(n^2)\) | 否 |
插入排序 | \(O(n)\) | \(O(n^2)\) | \(O(n^2)\) | 是 |
计数排序(设值域为 w) | \(O(n+w)\) | \(O(n+w)\) | \(O(n+w)\) | 是 |
归并排序 | \(O(nlogn)\) | \(O(nlogn)\) | \(O(nlogn)\) | 是 |
快速排序 | \(O(nlogn)\) | \(O(n^2)\) | \(O(nlogn)\) | 否 |
杂项
- 前后缀表式转中缀表达式:栈