图的应用(最小生成树,拓扑排序)

126 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情

介绍

应用图解决现实问题是我们使用图这种数据结构的原因所在。
最小生成树是图的应用中很常见的一个概念,一个图的最小生成树不是唯一的,但最小生成树的边的权值之和纵使唯一的。最小生成树的算法主要有Prim算法和Kruskal算法。这两种算法都是基于贪心算法策略(只考虑眼前的最佳利益,而不考虑整体的效率)。
拓扑排序是指由一个有向无环图的顶点组成的序列,此序列满足以下条件:

  1. 每个顶点出现且仅出现一次
  2. 若顶点A在序列中排在顶点B之前,则图中不存在顶点B到顶点A的路径。

最小生成树

Prim算法

Prim算法非常类似与寻找图的最短路径的Dijkstra算法。
算法思路:

  1. 首先将图的任一节点加如树中
  2. 之后选择一个与当前顶点最近的节点接入树中。
  3. 循环 2直到所有节点均被接入树中。

Prim算法的时间复杂度是O(V*V),不依赖于E,因此他适合边稠密的图的最小生成树。

Kruskal算法

克鲁斯卡尔算法是一种按权值的递增次序选择合适的边来构造最小生成树的方法。
算法思路:

  1. 初始时只有n个顶点而无边的非连通图,每个顶点自成一个连通分量
  2. 按照边的权值由小到大,不断选取当前未被选取过且权值最小的边
  3. 若该边依附的顶点落在图的不同的连通分量,则将该边加入树中,否则舍去,直到所有顶点都在一个连通分量。

Kruskal的时间复杂度为O(Elog2E),因此此算法适合构造边稀疏而顶点稠密的图的最小生成树。

拓扑排序

对一个AOV网进行拓扑排序的算法有很多,下面介绍一种。

  1. 从AOV网中选择一个没有前驱的节点进行输出
  2. 从网中删除该顶点和所有以它为起点的有向边
  3. 重复1和2,直到当前的AOV网为空,或者当前网中不存在无前驱的顶点为止。后面一种情况说明有向图中必然存在环。

由于输出每个顶点的同时还要删除以它为起点的边,故采用邻接表存储拓扑排序的时间复杂度为O(V+E)。采用邻接矩阵存储拓扑排序的时间复杂度是O(V*V)。
注;若一个顶点有多个直接后继,则拓扑排序的结果通常不唯一。