参考青岛大学–王卓老师
一、图的定义和术语
有向图、无向图、稀疏图、稠密图、网、邻接、关联、顶点的度(与该顶点相关联的边的数目)、入度、出度、路径、路径长度、回路、简单路径、连通图(在无向图中,对于任意两个顶点v/u,都存在 v到u的路径,则该图为连通图)、子图、连通分量(无向图的极大连通子图称为连通分量)、强连通分量、极小连通子图、生成树、生成森林
二、图的存储结构
1.邻接矩阵
无向图的邻接矩阵
对称的,顶点i的度=第i行1的个数
特例:完全图的邻接矩阵中,对角元素为0,其余元素为1
有向图的邻接矩阵
可能是不对称的,顶点的出度=第i行元素之和,顶点的入度=第i列元素之和,顶点的度=第i行元素之和+第i列元素之和
网
算法思想:
- 输入总顶点数和总边数。
- 依次输入点信息存入顶点表。
- 初始化邻接矩阵,使每个权值初始化为极大值。
- 构造邻接矩阵。
2.邻接表
邻接表表示法(链式)
按照编号顺序将顶点数据存储在一维数组中
关联同一顶点的边,用线性链表存储
如果有权值则放在info中
无向图邻接表(每条边存储两次):
无向图邻接表特点:
- 邻接表不唯一
- 若无向图有n个 顶点、e条边,则其邻接表需要n个头结点和2e个表结点。适合存储稀疏图
- 有几个表结点就是有几个度
有向图邻接表:
有向图邻接表特点:
- 顶点的出度为单链表中的结点个数
- 顶点的入度为值域为i-1的结点个数
逆邻接表恰好相反
算法:
- 输入总顶点数和总边数
- 建立顶点表,依次输入点的信息存入顶点表中,使每个表头结点的指针域初始化为null
- 创建邻接表,依次输入每条边依附的两个顶点,确定两个顶点的序号i和j,建立边结点,将此边结点分别插入到两结点对应的两个边链表的头部(头插法)
邻接矩阵是惟一的,而邻接表并不是惟一的
十字链表法(解决有向图):
邻接多重表(解决无向图):
三、图的遍历
用标记数组visited[i],做标记
1.dfs
一条路走到底,然后再返回
邻接矩阵:
2.bfs
按照层进行访问,层次遍历
用邻接表更简单,利用队列的思想
四、图的应用
1.最小生成树
生成树:既连通又不存在回路的图
最小生成树:使各边权值之和最小的树,称为该网的最小生成树
实例:n个城市建立通信网
利用MST性质,实际上贪心算法,将权值最小的边划入生成树
避圈法有Prim算法和Kruskal算法
Prim算法
选择点,适合稠密图
Kruskal算法
选择边,适合稀疏图
补充:破圈法
- 找到图中一个圈
- 删除其中权最大的边
- 重复以上操作直到没有圈
2.最短路
从一个点起点到终点的最短路径,并不一定需要包含每一个顶点,也不一定每一个边
单源最短路Dijkstra
Dijkstra
- 初始化
- 选择
- 更新
所有顶点间的最短路径Floyd
依次加入顶点试探值是否有变化
起初,全部是直达的
然后在这上面不断加点
3.拓扑排序
针对有向无环图,不允许有回路
删除没有前驱的顶点并输出,删除它的尾弧
拓扑排序可以判断AOV中是否存在环
4.关键路径
AOE用边来表示活动的网络,顶点表示事件,弧表示活动,弧的权表示活动的持续时间
关键路径:从原点到汇点路径长度最长的路径。
ve(vj)表示事件vj的最早的发生时间,正序的从第一个结点开始的,取max,ve[k] = max(ve[j] + len<Vj, Vk>)
vl(vj)表示事件vj的最迟发生时间,倒序的从最后一个结点开始的,取min,vl[k] = min(vl[j] - len<Vj, Vk>)
e(i)表示活动ai的最早开始的时间
l(i)表示活动ai最迟开始的时间
(这个地方看了好久QAQ,总算理解些)