08 图 | 数据结构与算法
1. 图的基本概念
1. 图的定义
-
图:图 是由顶点的有穷非空集合和顶点之间边的集合组成的一种数据结构,通常表示为:
, 是顶点的集合, 是顶点之间边的集合。通常用顶点表示数据元素,边表示数据元素之间的逻辑关系 -
图的分类
- 无向图
- 无向边:如果顶点
之间的边之间没有方向,则称这条边为 无向边,表示为 - 无向图:如果图的任意两个顶点之间的边都是无向边,那么该图被称为 无向图
- 无向边:如果顶点
- 有向图
- 有向边:如果顶点
之间的边之间有方向,则称这条边为 有向边(弧),表示为 ,其中 被称为 弧尾, 被称为 弧头 - 有向图:如果图的任意两个顶点之间的边都是有向边,那么该图被称为 有向图
- 有向边:如果顶点
- 无向图
-
完全图
- 无向图:在具有
个顶点的无向图中,最大弧数为 - 有向图:在具有
个顶点的有向图中,最大弧数为
- 无向图:在具有
-
顶点的度
- 无向图的度:一个顶点
的度是与它相关联的 边的条数 - 有向图的度
- 出度:以顶点
为 弧尾(起点) 的弧的数目 - 入度:以顶点
为 弧头(终点) 的弧的数目
- 出度:以顶点
- 无向图的度:一个顶点
-
路径
- 无向图的路径:在无向图
中,如果存在顶点序列 ,使得 ,则称该序列为从 到 的一条 路径 - 有向图的路径:在有向图
中,如果存在顶点序列 ,使得 ,则称该序列为从 到 的一条 有向路径 - 路径的 长度:路径上边的数量
- 带权图的路径长度:路径上各边的权值之和
- 简单路径:如果路径上的各顶点
互不相同,则称这样的路径为 简单路径
- 无向图的路径:在无向图
-
子图:如果图
,其中 ,那么 是 的 子图 -
连通图和连通分量(无向图)
- 连通性:顶点的连通性:在无向图中,若从顶点
到顶点 有路径,则称顶点 与 是连通的 - 连通图:如果一个无向图中任意一对顶点都是连通的, 则称此图是 连通图
- 连通分量:非连通图的极大连通子图叫做 连通分量
- 连通性:顶点的连通性:在无向图中,若从顶点
-
强连通图与强连通分量
- 顶点的强连通性:在有向图中, 若对于每一对顶点
和 ,都存在一条从 到 和从 到 的有向路径,则称顶点 与 是 强连通的 - 强连通图:如果一个有向图中任意一对顶点都是强连通的, 则称此有向图是 强连通图
- 强连通分量:非强连通图的极大强连通子图叫做 强连通分量
- 顶点的强连通性:在有向图中, 若对于每一对顶点
-
生成树:假设一个连通图有
个顶点和 条边,其中 条边和 个顶点构成一个极小连通子图,称该极小连通子图为此连通图的 生成树
2. 图与其他数据结构的比较
- 比较一
1. 在线性结构中,数据元素之间仅具有线性关系(1:1)
2. 在树结构中,结点之间具有层次关系(1:n)
3. 在图结构中,任意两个点之间都可能有关系(m:n) - 比较二
1. 在线性结构中,数据元素之间的关系为 前驱和 后继
2. 在树结构中,结点之间的关系为 双亲和孩子
3. 在图结构中,顶点之间的关系为 邻接
3. 图的存储
-
邻接矩阵表示法
-
邻接表
-
有向图的十字链表
-
无向图的邻接多重表
2. 图的遍历
1. 图的遍历
- 定义:从图中某一顶点出发访遍图中其余顶点,且使每个顶点仅被访问一次,就叫做图的遍历
- 分类:深度优先搜索
和广度优先搜索
2. 深度优先搜索
-
定义:在访问图中某一起始顶点
后,由 出发,访问它的任一邻接顶点 ;再从 出发,访问与 邻接但还没有访问过的顶点 ;然后再从 出发,进行类似的访问;如此进行下去,直至到达所有的邻接顶点都被访问过的顶点 为止。接着,退回一步,退到前一次刚访问过的顶点,看是否还有其它没有被访问的邻接顶点。如果有,则访问此顶点,之后再从此顶点出发,进行与前述类似的访问;如果没有,就再退回一步进行搜索。重复上述过程,直到连通图中所有顶点都被访问过为止 -
算法:运用栈(递归)结构存储待
的结点 -
时间复杂度
- 邻接表:扫描边的时间为
;而且对所有顶点递归访问1次,所以遍历图的时间复杂性为 - 邻接矩阵:查找每一个顶点的所有的边,所需时间为
,则遍历图中所有的顶点所需的时间为
- 邻接表:扫描边的时间为
3. 广度优先搜索
-
定义:在访问了起始顶点
之后, 由 出发, 依次访问 的各个未被访问过的邻接顶点 , 然后再顺序访问 的所有还未被访问过的邻接顶点。再从这些访问过的顶点出发,再访问它们的所有还未被访问过的邻接顶点,如此做下去,直到图中所有顶点都被访问到为止 -
算法:运用队列结构存储待
的结点 -
时间复杂度
- 邻接表:遍历图的时间复杂性为
- 邻接矩阵:遍历图中所有的顶点所需的时间为
- 邻接表:遍历图的时间复杂性为
3. 并查集
1. 并查集的定义
- 并查集:对于一个集合
,我们还可以对集合 进一步划分: ,并查集 希望能够快速确定 中的两两元素是否属于 的同一子集 - 并查集的基本结构:用树表示集合,不同的树是不同的集合,并查集中包含了多棵树,表示并查集中不同的子集,树的集合是森林,所以并查集属于森林
2. 并查集的基本操作
- 初始化
find
:返回node
所属集合树的根节点join
:合并两个点所属的集合
3. 并查集的优化
- 优化原因:上面的实现,每一次
find
时间复杂度为 , 为树的高度,因为没有对树做特殊处理,所以树的不断合并可能会使树严重不平衡,最坏情况每个节点都只有一个子节点,时间复杂度为 - 优化方法
- 方法一:按秩合并:记录这棵树的高度(记为
);接下来当合并两棵树时,先对两棵树的高度进行判断,如不同,则让高度小的树的根指向高度大的根 - 方法二:路径压缩:查询时我们需沿着元素所在的树从下往上查询,最终找到这棵树的根,表明这个元素与其根对应元素属于同一组。因为在此查询过程中我们会经过许多节点,而如果我们能将这个元素直接指向根节点,那么就能节省许多查询的时间。同时,在查询过程中,每次经过的节点,我们都可以同时将他们一起直接指向根节点。这样做的话,我们再查询这些节点时,就能很快找到根
- 方法一:按秩合并:记录这棵树的高度(记为
4. 最小生成树
1. 最小生成树
- 生成树的代价:设
是一个无向连通网, 中的每一条边上有一个权值,生成树各边的权值之和被称为 生成树的代价 - 最小生成树
:在图 中的所有生成树中,代价最小的生成树被称为 最小生成树 - 最小生成树构造准则
- 尽可能用网络中权值最小的边
- 必须使用且仅使用
条边来联结网络中的 n个顶点 - 不能使用产生回路的边
2. 算法
-
基本思想:从连通网络
中的某一顶点 出发,选择与它关联的具有最小权值的边 ,将其顶点加入到生成树的顶点集合 中。以后每一步从一个顶点在 中,而另一个顶点不在 中的各条边中选择权值最小的边 ,把该边加入到生成树的边集中,把它的顶点加入到集合 中;如此重复执行,直到网络中的所有顶点都加入到生成树顶点集合 中为止 -
注意
- 若候选轻权边集中的轻权边不止一条,可任选其中的一条扩充到生成树中
- 连通图的最小生成树不一定是唯一的,但它们的权相等
- 设连通网络有
个顶点, 则该算法的时间复杂度为 ,它适用于边稠密的网络
-
算法
3. 算法
-
基本思想:设有一个有
个顶点的连通网络 ,最初先构造一个只有 个顶点,没有边的非连通图 图中每个顶点自成一个连通分量。当在 中选到一条具有最小权值的边时,若该边的两个顶点落在不同的连通分量上,则将此边加入到 中;否则将此边舍去,重新选择一条权值最小的边。如此重复下去,直到所有顶点在同一个连通分量上为止 -
算法
5. 拓扑排序
1. 网
网:用顶点表示活动,用有向边 表示活动间的优先关系。 必须先于活动 进行,这种有向图叫做顶点表示活动的AOV网络- 如果AOV网络中存在有向环,此
网络所代表的工程是不可行的 - 拓扑序列: 即将各个顶点 (代表各个活动)排列成一个线性有序的序列,使得所有弧尾结点都排在弧头结点的前面
- 拓扑排序:构造
网络全部顶点的拓扑有序序列的运算就叫做拓扑排序
2. 拓扑排序
-
基本思想:在
网络中选一个没有直接前驱的顶点,从图中删去该顶点, 同时删去所有它发出的有向边,重复以上步骤,全部顶点均已输出,拓扑有序序列形成,拓扑排序完成;图中还有未输出的顶点,但已跳出处理循环。说明图中还剩下一些顶点, 它们都有直接前驱。这时网络中必存在有向环 -
算法
6. 网
1. 网
网:如果在无有向环的带权有向图中,用有向边表示一个工程中的各项活动,用边上的权值表示活动的持续时间,用顶点表示事件,则这样的有向图叫做用边表示活动的网络,被称为 网 网络- 意义
- 完成整个工程至少需要多少时间(假设网络中没有环)
- 为缩短完成工程所需的时间, 应当加快哪些活动
- 源点与汇点:在
网络中, 有些活动顺序进行,有些活动并行进行,入度为零的点叫源点,出度为零的点叫汇点 - 关键路径:完成整个工程所需的时间取决于从源点到汇点的最长路径长度,即在这条路径上所有活动的持续时间之和,这条路径长度最长的路径就叫做关键路径
- 关键活动:关键路径上的活动为 关键活动
2. 关键路径求解算法
-
事件最早可能开始的时间
ve[i]
-
事件最迟允许发生的时间
vl[i]
- 概念:在保证汇点
在ve[n-1]
时刻完成的前提下,事件 的允许的最迟开始时间 - 算法:从
vl[n-1]=ve[n-1]
开始开始反推,vl[i] = min{vl[j] - time<vi, vj>}
- 概念:在保证汇点
-
活动开始的最早时间
e[k]
- 概念:设活动
ak
在带权有向边<vi, vj>
上,其持续时间为time<vi, vj>
,其最早发生时间e[k]=ve[i]
- 概念:设活动
-
活动最迟允许开始时间
l[k]
- 概念:
l[k]
是在不会引起时间延误的前提下, 该活动允许的最迟开始时间,l[k] = vl[j] - time<i, j>
- 概念:
-
时间余量
l[k]-e[k]
:表示活动ak
的最早可能开始时间和最迟允许开始时间的时间余量。l[k] == e[k]
表示活动ak
是没有时间余量的关键活动 -
vertex
1 2 3 4 5 6 7 8 ve
0 8 12 22 28 40 46 58 vl
0 8 12 22 28 40 46 58 由公式计算出:
edge(activity)
1 2 3 4 5 6 7 8 9 e
0 8 12 12 22 22 28 40 46 l
0 8 12 12 22 32 28 40 46 因此除了
a6
不是关键活动,其他都是,因此得出关键路径 -
算法
7. 最短路径
1. 最短路径问题
- 最短路径:如果图是一个带权图,则路径长度为路径上各边的权值之和,两个顶点之间的路径长度最短的路径为两个点之间的最短路径,其长度是 最短路径长度
- 算法
算法:边上权值非负情形的单源最短路径问题 算法:所有顶点之间的最短路径
2. 算法
-
基本思想:按路径长度的递增次序, 逐步产生最短路径的算法。首先求出长度最短的一条最短路径,再参照它求出长度次短的一条最短路径,依次类推,直到从顶点v到其它各顶点的最短路径全部求出为止
-
示例:计算从
v4
顶点到各顶点的最短路径(pre
表示连接的前驱点,dist
表示当前的最短路径长度)v1
v2
v3
v4
v5
v6
dist
20 0 15 pre
v4
v4
v4
v4
v4
v4
dist
30 20 ✔️ 15 pre
v2
v4
v4
✔️ v4
v4
dist
30 20 45 ✔️ 50 ✔️ pre
v2
v4
v1
✔️ v2
✔️ dist
30 ✔️ 45 ✔️ 50 ✔️ pre
v2
✔️ v1
✔️ v2
✔️ dist
✔️ ✔️ 45 ✔️ 50 ✔️ pre
✔️ ✔️ v1
✔️ v2
✔️ dist
✔️ ✔️ ✔️ ✔️ 50 ✔️ pre
✔️ ✔️ ✔️ ✔️ v2
✔️ dist
✔️ ✔️ ✔️ ✔️ ✔️ ✔️ pre
✔️ ✔️ ✔️ ✔️ ✔️ ✔️ 因此从顶点
v4
出发到其余顶点的最短路径及长度vertex
length
path
v1
30 v4->v2->v1
v2
20 v4->v2
v3
45 v4->v2->v1->v3
v4
0 v4
v5
50 v4->v2->v5
v6
15 v4->v6
-
算法
- 基于
dist[]
数组的 算法(时间复杂度 ,如果求每个点到各点的最短路径则 ) - 使用一个小根堆来寻找未确定节点中与起点距离最近的点的
算法
- 基于
3. 算法
- 基本思想:从初始的邻接矩阵
开始,递推地生成矩阵序列 - 递推公式:
- 路径记录:显然,
中记录了所有顶点对之间的最短路径长度。若要求得到最短路径本身,还必须设置一个路径矩阵 ,在第 次迭代中求得的path[i][j]
,是从i
到j
的中间点序号不大于 的最短路径上顶点i的后继顶点。算法结束时,由path[i][j]
的值就可以得到从i
到j
的最短路径上的各个顶点 - 算法
__EOF__

本文链接:https://www.cnblogs.com/RadiumGalaxy/p/17069446.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话