数据结构与算法-图
图的基本概念
顶点集V
和边集E
.- | V | : 顶点和边的数目. | E | : 边的数目.
无向图 :
(v,w)或(w,v)有向图 :
<v,w>简单图 :
①不存在顶点到自身的边 ②不存在重复边.多重图.
顶点的度 :
对于无向图
,指的是依附与该定点的边的条数,称为TD(v);总TD = 2e
对于有向图
,入度为以顶点v为终点的有向边束缚,记为ID(Vi);出度为以顶点v为起点的有向边束缚,记为从OD(Vi);顶点v的度为入度和出度之和,记为TD(v) = ID(v) + OD(v).在n个顶点,e条边的有向图中,总ID = 总OD = e
.路径 :
顶点到顶点之间的顶点序列.回路 :
第一个顶点和最后一个顶点相同的路径称为回路或环.简单路径 :
再路径序列中,顶点不重复
出现的路径称为简单路径.简单回路 :
除第一个顶点和最后一个顶点外,其余顶点不重复出现的回路.路径长度 :
路径上边的数点到点的距离 :
从顶点v到顶点u的最短路径
若存在,则此路径的长度称为从u到v的距离,若从u到v根本不存在路径,则该距离为无穷大∞.连通:
无向图中,若从顶点v到w有路径存在,则称v和w是连通的.强连通:
有向图中,若从顶点v到w和从顶点w到v之间都有路径,则称这两个顶点是强连通的.连通图:
无向图中任意两个顶点都是连通的.若G是连通图
,则最少
有n-1
条边.若G是非连通图
,则最多
可能有 C n − 1 2 C_{n-1}^{2} Cn−12条边[即(n-1)(n-2)/2,等同于n-1个节点的完全连通图的边数]强连通图:
有向图中任意两个顶点都是强连通的.若G是强连通图,则最少有n条边(形成回路).子图:
生成子图:
包含所有顶点的子图极大连通子图:
必须连通的子图,且包含尽可能多的顶点和边.- 无向图中的极大连通子图称为
连通分量
.eg: 中国铁路网中,海南岛铁路网,大陆铁路网,台湾铁路网.[注意长三角铁路网不是!因为其可以继续向外增加边和顶点且保持连通性] - 有向图中的极大强连通分量称为
强连通分量
. 生成树:
无向连通图
中必须连通的子图
,且包含所有的顶点
和尽可能少的边
.若此图有n个顶点,则其生成树有n-1条边,砍去一条会变成非连通图,加上一条会形成回路.生成树可能不唯一非连通图中
,连通分量的生成树构成了非连通图的生成森林
.- 边可以带有权值,
带权路径程度
即为一条路径上索友边的权值之和. 无向完全图:
无向图中任意两个顶点之间都存在边.- 若无向图的定点数|V| = n,则|E| ∈[0, C n 2 C_{n}^{2} Cn2]=[0,n(n-1)/2]
有向完全图:
有向图中任意两个顶点之间都存在方向相反的两条弧.- 若有向图的定点数|V| = n,则|E| ∈[0,2 C n 2 C_{n}^{2} Cn2]=[0,n(n-1)]
- 边很少的图称为
稀疏图
,反之称为稠密图
树:
不存在回路,且连通的无向图.n个顶点的树,必有n-1条边.有向树:
一个顶点的入度为0,其余顶点的入度均为1的有向图.
邻接矩阵法
-
基本
-
带权图(网)
可以用宏定义常量来表示无穷.一般使用int的上限INFINITY
-
求节点的度
无向图
:
第i个结点的度 = 第i行(或第i列)的非零元素个数
有向图
:
第i个结点的出度 = 第i行的非零元素个数
第i个结点的入度 = 第i列的非零元素个数
第i个结点的度 = 第i行、第i列的非零元素个数之和
邻接矩阵法求顶点的度/出度/入度的时间复杂度
为 O(|V|) -
空间复杂度
O( ∣ V ∣ 2 |V|^{2} ∣V∣2) ——只和顶点数相关,和实际的边数无关
适合
用于存储稠密图
(边多的图)
无向图的邻接矩阵是对称矩阵,可以压缩存储(只存储上三角区/下三角区) -
邻接矩阵法的性质
设图G的邻接矩阵为A(矩阵元素为0/1),则 A n A ^{n} An 的元素 A n A ^{n} An [i][j]等于由顶点i到顶点j的长度为n的路径的数目
邻接表法(顺序 + 链式存储)
- 空间复杂度
无向图
: 边结点的数量是2|E|,整体空间复杂度为O(|V| + 2|E|). 存在冗余边节点.
有向图
: 边结点的数量是|E|,整体空间复杂度为O(|V| + |E|) - 图的
邻接矩阵
表示方式唯一
,图的邻接表
表示方式并不唯一
- 图的
邻接表
表示方式找有向图的入边不方便,适合存储稀疏图
.
十字链表存储有向图
邻接矩阵的缺点: 空间复杂度高 O(
∣
V
∣
2
|V|^{2}
∣V∣2)
邻接表的缺点: 找顶点的入边不方便
- 空间复杂度
O(|V|+|E|)
如何找到指定顶点的所有出边?——顺着绿色线路找
如何找到指定顶点的所有入边?——顺着橙色线路找 - 注意:十字链表只用于存储有向图
邻接多重表存储无向图
邻接表存储无向图,每条边对应两份冗余信息,且删除顶点、删除边等操作时间复杂度高.
- 空间复杂度
每条边只对应一份数据
O(|V|+|E|)
删除边、删除节点等操作很方便. - 注意:邻接多重表只适用于存储无向图
最短路径问题
单源最短路径
BFS算法(无权图或所有边权值都相等)
Dijkstra算法(带权图或无权图)
带权路径长度
: 当图是带权图时,一条路径上所有边的权值之和,称为该路径的带权路径⻓度- 算法流程和思路:
初始
: 初始化初始化三个数组信息,final[n]
标记各顶点是否已找到最短路径;dist[n]
表示最短路径的长度,初始时每个点的路径长度都为∞;path[n]
表示路径点的前趋.
第一步
: 将起点v0
添加进final数组中,同时dist[0]也应该设置为0, 其余vo直接相连的点的最短路径dist[i]也设置为对应值.
第二步
: 遍历所有点,寻找此时未找到最短路径final[i] == false
且dist[i]最小
的顶点vi,将其加入已访问序列final.
第三步
: 更新未到达点的最短路径.因为我们增加了一个新的可达的点,通过这个点可能会让原先某个点新增一条更短的可达路径.因此需要更新操作.即检查所有邻接自第二步中Vi 的顶点,若其 final 值为false,则更新 dist 和 path 信息
.
第四步
: 重复第二步和第三步,直到所有的点都已访问. - Dijkstra 算法不适用于有负权值的带权图