数据结构之图:有向图的拓扑排序,Python代码实现——26

有向图的拓扑排序

拓扑排序介绍

什么是拓扑排序?

  • 一个有向图的拓扑排序(Topological sort 或 Topological ordering)是根据其有向边从顶点U到顶点V对其所有顶点的一个线性排序
  • 举个例子:让一个拓扑排序的图中的所有顶点代表某项要执行的任务组合,那么它的边就可以代表要执行要执行其中某一项任务必须要先先于另外一项任务的限制条件,在这个例子中,拓扑排序就是这项任务组合的有效排序
    在这里插入图片描述

有向图中的环

知道了拓扑排序可以用来解决优先级问题后,还要确保要解决排序问题的图中没有环:

  • 如果学习x课程前必须先学习y课程,学习y课程前必须先学习z课程,学习z课程前必须先学习x课程,那么一定是有问题了, 我们就没有办法学习了,因为这三个条件没有办法同时满足。其实这三门课程x、y、z的条件组成了一个环:
    在这里插入图片描述

如何检测有向图中的环

借助一个列表ontrack,其索引代表图中的顶点

  1. 在如果当前顶点正在搜索,则把对应的ontrack数组中的值改为True;
  2. 如果当前顶点搜索完毕,则把对应的ontrack数组中的值改为False;
  3. 如果即将要搜索某个顶点,但该顶点在当前搜索时标识为True,则图中有环;

基于DFS使用Python代码实现拓扑排序

检测图中的环

检测的目标,对应的实现了这张图的类方法:点击回到上一节查看代码
在这里插入图片描述

主要属性和方法

  1. 构造方法__init__()中
    graph为需要进行拓扑排序的图;marked标记当前节点是否已经搜索完毕;has_cycle用于标记当前图中是否存在环;ontrack标记当次所处搜索中顶点是否已经遍历过
  2. 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实现图中顶点的拓扑排序

主要属性方法设计
  1. 相比于之前的图新增了一个stack,stack是一个列表(看做栈),按顺序记录拓扑排序所走过的顶点
  2. dfs() 使用DFS算法对顶点进行拓扑排序并将结果储存到stack列表中
  3. 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]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/469483.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

图像分类_02神经网络(NN)简介:定义+ 感知机+历史

2.2.1 什么是神经网络 人工神经网络( Artificial Neural Network, 简写为ANN)也简称为神经网络(NN)。是一种模仿生物神经网络(动物的中枢神经系统,特别是大脑)结构和功能的 计算模型…

图像分类_03分类器及损失:线性分类+ SVM损失+Softmax 分类+交叉熵损失

2.3.1 线性分类 2.3.1.1 线性分类解释 上图图中的权重计算结果结果并不好,权重会给我们的猫图像分配⼀个⾮常低的猫分数。得出的结果偏向于狗。 如果可视化分类,我们为了⽅便,将⼀个图⽚理解成⼀个⼆维的点,在下⾯坐标中显示如下…

数据结构之图:加权无向图与寻找最小生成树,Python——27

加权无向图与prim算法和Kruskal算法寻找最小生成树 加权无向图的介绍 引入 加权无向图是一种为每条边关联一 个权重值或 是成本的图模型。这种图能够自然地表示许多应用。在一副航空图中,边表示航线,权值则可以表示距离或是费用。在一副电路图中,边表示导线,权值则可能表示导…

图像分类_04神经网络最优化过程:反向传播+代码实现

logistic模型原理与推导过程分析(1)https://blog.csdn.net/qq_39237205/article/details/121031296https://blog.csdn.net/qq_39237205/article/details/121031296 logistic模型原理与推导过程分析(2)https://blog.csdn.net/qq_3…

数据结构之图:加权有向图与dijkstra算法找到最短路径,Python——28

加权有向图与dijkstra算法找到最短路径 加权有向图的构造 最短路径问题与最短路径树 最短路径问题(The shortest path problem)定义 最短路径可以是时间花费最短,也可以是距离最短,或是花费最少在图论中,最短路径问…

李沐动手学深度学习pytorch :问题:找不到d2l包,No module named ‘d2l’

同学你好!本文章于2021年末编写,已与实际存在较大的偏差! 故在2022年末对本系列进行填充与更新,欢迎大家订阅最新的专栏,获取基于Pytorch1.10版本的理论代码(2023版)实现, Pytorch深度学习理论篇(2023版)…

解决loaded more than 1 DLL from .libs和No metadata found in lib\site-packages两个错误

### 卸载numpy pip uninstall numpy 解决No metadata found in lib\site-packages 去这个文件夹下找到numpy的两个文件夹 删除 然后重新输入pip install numpy

ERROR 2002 (HY000): Can‘t connect to local MySQL server through socket ‘/var/run/mysqld/mysqld.sock‘

启动数据库时报错,代码ERROR 2002 (HY000) 报错截图: 原因:网络环境发生改变,mysql配置文件中绑定的IP与现在系统的IP不一致 解决:修改配置文件中绑定的IP地址为本系统的IP地址 使用命令: sudo vi /etc/…

图像目标分割_1 概述

6.1.1 什么是目标分割 定义:在计算机视觉领域,图像分割(Object Segmentation)指的是将数字图像细分为多个图像子区域(像素的集合)的过程。 图像分割的目的:简化或改变图像的表示形式&#xff0…

字符数组和strcpy

已知strcpy函数的原型是char *strcpy(char *strDest, const char *strSrc);,其中strDest是目的字符串,strSrc是源字符串。 (1)Write the function strcpy, dont call C/C string library.(不调用C/C的字符串库函数&…

Django开发中问题和报错集合

记录django项目开发过程中的遇到的问题,导致原因和已经奏效的解决方法 常见报错UnicodeDecodeError: ‘utf-8’ codec can’t decode byte 0xbc in position 852: invalid start byte 这个问题在一些电脑上做django开发时经常出现 要么是py文件运行是就报这个类似…

图像目标分割_2 FCN(Fully Convolutional Networks for Semantic Segmentation)

6.2.1 FCN 背景介绍 图像语义分割:给定一张图片,对图片上每一个像素点进行分类!但是与图像分类目的不同,语义分割模型要具有像素级的密集预测能力才可以。 6.2.2 FCN介绍 6.2.2.1 全卷积网络 全卷积网络,模型由卷积…

求4个数字组成的不重复三位数,Python简洁解法

求4个数字组成的不重复三位数,Python解法 题目要求: 求所有由5,6,7,8组成的数字不重复的三位数 不重复的三位数,即不能出现555,566这种 通过分析,可以使用画树的方法来确定要求的三位数的值与个数 按照上图所示可以确定由5&am…

图像目标分割_3 SegNet + U-Net

6.3.1 SegNet背景 SegNet的主要动机是场景理解的应用。 难点:因此它在设计的时候考虑了要在预测期间保证内存和计算时间上的效率。分割的任务其实应用非常地广,需要理解各个像素之间的关系,比如要区分出人行道和车行道,建筑物和…

MIPI屏数据发送命令解析

MIPI数组发送那里有一个数组,这个数组包含寄存器和寄存器的值: 相当于: 0XC480寄存器下参数0X9C; 0XFF00寄存器下参数0XFF,0XFF,0XFF; 0XC0B5 尝试一下寄存器 0x08 0x18 0x48 0x58 试一下能不能旋转

面向对象之类的内建函数

类的特殊成员 上文介绍了Python的类成员以及成员修饰符,从而了解到类中有字段、方法和属性三大类成员,并且成员名前如果有两个下划线,则表示该成员是私有成员,私有成员只能由类内部调用。无论人或事物往往都有不按套路出牌的情况&…

图像目标分割_4 DeepLab-V1

6.4.1 DeepLab 背景 相比于传统的视觉算法(SIFT或HOG),Deep-CNN以其end-to-end方式获得了很好的效果。这样的成功部分可以归功于Deep-CNN对图像转换的平移不变性(invariance),这根本是源于重复的池化和下采样组合层。平移不变性增强了对数据分层抽象的能…

图像目标分割_5 DeepLab V2 V3 V3+

6.5.1 DeepLab V2 6.5.1.1 改变特点 atrous convolution采用ASPP ( atrous spatial pyramid pooling) 多尺度获得更好的分割效果合并深度卷积网络和概率图模型方法,增强对物体边界的定位。基础层由VGG16转为ResNet 和v1不同: 通过多尺度输入处理或者多…

Python导包、模块报错的问题

import报错No module named "xxx"的问题 如何将指定目录作为项目根目录,让项目根目录下的包/模块都可以直接导入?(linux下) Python导入模块时,解释器如何定位模块: 1.当前目录 2.内置模块列表 3…

CC2540 串口0 通道2配置

从图里面可以看出来,串口0有两个通道,一个通道是P02 P03两个GPIO口。 还有一个通道是P14 P15两个GPIO口。 在软件配置的时候,主要是配置的是一个通道相关的寄存器。 7.6.4 USART 0 The SFR register bit PERCFG.U0CFG selects whether to u…