数据结构之图:有向图的拓扑排序,Python代码实现——26
有向图的拓扑排序
拓扑排序介绍
什么是拓扑排序?
- 一个有向图的拓扑排序(Topological sort 或 Topological ordering)是根据其有向边从顶点U到顶点V对其所有顶点的一个线性排序
- 举个例子:让一个拓扑排序的图中的所有顶点代表某项要执行的任务组合,那么它的边就可以代表要执行要执行其中某一项任务必须要先先于另外一项任务的限制条件,在这个例子中,拓扑排序就是这项任务组合的有效排序
有向图中的环
知道了拓扑排序可以用来解决优先级问题后,还要确保要解决排序问题的图中没有环:
- 如果学习x课程前必须先学习y课程,学习y课程前必须先学习z课程,学习z课程前必须先学习x课程,那么一定是有问题了, 我们就没有办法学习了,因为这三个条件没有办法同时满足。其实这三门课程x、y、z的条件组成了一个环:
如何检测有向图中的环
借助一个列表ontrack,其索引代表图中的顶点
- 在如果当前顶点正在搜索,则把对应的ontrack数组中的值改为True;
- 如果当前顶点搜索完毕,则把对应的ontrack数组中的值改为False;
- 如果即将要搜索某个顶点,但该顶点在当前搜索时标识为True,则图中有环;
基于DFS使用Python代码实现拓扑排序
检测图中的环
检测的目标,对应的实现了这张图的类方法:点击回到上一节查看代码
主要属性和方法
- 构造方法__init__()中
graph为需要进行拓扑排序的图;marked标记当前节点是否已经搜索完毕;has_cycle用于标记当前图中是否存在环;ontrack标记当次所处搜索中顶点是否已经遍历过 - dfs() 使用DFS算法对图进行遍历,判断图中是否存在环
Python代码实现
class DirectedCycle:def __init__(self, graph):self.graph = graphself.marked = [False for _ in range(self.graph.num_vertices)]self.has_cycle = Falseself.ontrack = [False for _ in range(self.graph.num_vertices)]def dfs(self):"""We need to search every vertex of this graph"""def dfs(index):self.marked[index] = Trueself.ontrack[index] = Truefor vertex in self.graph.adj_list[index]:if not self.ontrack[vertex]:dfs(vertex)if self.ontrack[vertex]:self.has_cycle = Truereturnself.ontrack[index] = Falsefor i in range(self.graph.num_vertices):if not self.marked[i]:dfs(i)if __name__ == '__main__':graph = Digraph(5)graph.point_edge(3, 0)graph.point_edge(0, 2)graph.point_edge(2, 1)graph.point_edge(1, 0)graph.point_edge(1, 4)DC = DirectedCycle(graph)print(DC.has_cycle)DC.dfs()print(DC.has_cycle)
运行结果
False
True
使用DFS实现图中顶点的拓扑排序
主要属性方法设计
- 相比于之前的图新增了一个stack,stack是一个列表(看做栈),按顺序记录拓扑排序所走过的顶点
- dfs() 使用DFS算法对顶点进行拓扑排序并将结果储存到stack列表中
- sort_vertices() 返回排序后的顶点
排序步骤
点击查看图对应的类方法
Python代码实现
class DepthFirstOrder:def __init__(self, graph):self.graph = graphself.marked = [False for _ in range(self.graph.num_vertices)]self.stack = []def dfs(self):"""Search each vertex and rank its order"""def dfs(index):self.marked[index] = Truefor x in self.graph.adj_list[index]:if not self.marked[x]:dfs(x)self.stack.insert(0, index)for i in range(self.graph.num_vertices):# for i in [5, 4, 3, 2, 1, 0]:if not self.marked[i]:dfs(i)return self.stackdef sort_vertices(self):return self.dfs()if __name__ == '__main__':graph = Digraph(6)# graph.point_edge(0, 3)graph.point_edge(0, 2)graph.point_edge(0, 3)graph.point_edge(2, 4)graph.point_edge(3, 4)graph.point_edge(4, 5)graph.point_edge(1, 3)print(graph.adj_list)DF = DepthFirstOrder(graph)print(DF.sort_vertices())
运行结果:
[[2, 3], [3], [4], [4], [5], []]
[1, 0, 3, 2, 4, 5]
排序结果会受到对顶点遍历的顺序影响,但是最终结果一定会是一条有效的符合逻辑的排序
检测一张图是否有环,并进行拓扑排序
调用前面所实现的方法即可,点击查看代码中使用到的图对应的类方法
from Structure.graph.digraph import Digraph
from Structure.graph.DepthFirstOrder import DepthFirstOrder
from Structure.graph.DirectedCycle import DirectedCycleclass TopoLogical:def __init__(self, graph):self.order = Noneself.cycle = DirectedCycle(graph)if not self.cycle.has_cycle:DFO = DepthFirstOrder(graph)self.order = DFO.sort_vertices()def has_cycle(self):# return self.cycle.has_cyclereturn not self.orderdef stack(self):return self.orderif __name__ == '__main__':graph = Digraph(6)graph.point_edge(0, 2)graph.point_edge(0, 3)graph.point_edge(2, 4)graph.point_edge(3, 4)graph.point_edge(4, 5)graph.point_edge(1, 3)print(graph.adj_list)TL = TopoLogical(graph)print(TL.has_cycle())print(TL.stack())
运行结果
[[2, 3], [3], [4], [4], [5], []]
False
[1, 0, 3, 2, 4, 5]
数据结构之图:有向图的拓扑排序,Python代码实现——26相关推荐
- 数据结构——AOV图与算法——拓扑排序
AOV图:以有向图中的顶点来表示活动,以有向边来表示活动之间的先后次序关系. 拓扑排序:对一个有向无环图(AOV)进行活动先后的排序方法 拓扑排序思路: 1.统计所有节点的入度 2.把所有入度为0的节 ...
- aov建立Java模拟,数据结构之---C语言实现拓扑排序AOV图
//有向图的拓扑排序 //杨鑫 #include #include #include #define MAX_NAME 3 #define MAX_VERTEX_NUM 20 typedef int ...
- 在linux下实现拓扑排序,数据结构——有向图(拓扑排序算法)
package zieckey.datastructure.study.graph; /** * 有方向图 * * @author zieckey */ public class DirectedGr ...
- (数据结构)有向图的拓扑排序 Kahn算法
拓扑排序是对有向无圈图的顶点的一种排序,使得如果存在一条从vi到vj的路径,那么在排序中,vi必须出现在vj的前面. 首先,我们需要准备一个vector<int> link[maxn],l ...
- 有向图的拓扑排序的理解和简单实现(Java)
如果图中存在环(回路),那么该图不存在拓扑排序,在这里我们讨论的都是无环的有向图. 什么是拓扑排序 一个例子 对于一部电影的制作过程,我们可以看成是一个项目工程.所有的工程都可以分为若干个" ...
- 拓扑排序之java实现_有向图和拓扑排序Java实现
package practice; import java.util.ArrayDeque; import java.util.Iterator; import java.util.Stack; pu ...
- 图——深度优先遍历(DFS)实现有向无环图的逆拓扑排序
对图的深度遍历与对树的深度遍历思想类似,采用的是递归函数的办法. 如果是非连通图,则DFS遍历所有顶点即可. //Graph 图 //vertex 顶点,用一个int型变量表示//返回有向图G中顶点v ...
- java 有向无环图 树_拓扑排序-有向无环图(DAG, Directed Acyclic Graph)
条件: 1.每个顶点出现且只出现一次. 2.若存在一条从顶点 A 到顶点 B 的路径,那么在序列中顶点 A 出现在顶点 B 的前面. 有向无环图(DAG)才有拓扑排序,非DAG图没有拓扑排序一说. 一 ...
- 图的应用 | 拓扑排序
拓扑序不唯一 一个图存在拓扑序 等价于 该图为有向无环图 1.有向图的拓扑排序实现: 辅助数据结构: 记录入度的数组 indegree[]: 初始化:创建的时候同步初始化: 队列zero:记录当前入 ...
最新文章
- python代码统计字符串中大写字符、小写字符、特殊字符以及数值字符出现的次数
- STL容器的基本特性和特征
- 遍历系统的所有ObjectType和TypeIndex
- 插入排序之——希尔排序(c/c++)
- 第一章---对象导论
- Javascript(6)
- include 路由 php,PHP简单路由
- CALL注入--扫雷辅助(二)
- Codeforces Round #705 (Div. 2) D. GCD of an Array 质因子分解 + stl维护
- winged edge翼边
- Java工作笔记-对反射的进一步理解
- 汇编语言:编写code段中代码,将a段和b段中的数据依次相加,将结果放到c段
- Lua学习笔记(5): 表
- 基于slicer开发(简化功能与插件开发)
- 天天生鲜项目——商品详情页
- (matlab)地震数据频谱分析-频谱图代码
- 前端必备:六款CSS工具让代码充满魅力
- 深度学习环境安装之显卡驱动程序安装
- 仿网易LOFTER视差滚动列表
- 【EtherCAT分析】三、EtherCAT从站设备描述文件设计