当前位置: 首页 > news >正文

数据结构与算法Python版 拓扑排序与强连通分支

文章目录

  • 一、图的应用-拓扑排序
  • 二、图的应用-强连通分支


一、图的应用-拓扑排序

拓扑排序Topological Sort

  • 工作流程图得到工作次序排列的算法,称为“拓扑排序”
  • 拓扑排序处理一个有向无环图DAG,输出顶点的线性序列。使得两个顶点v,w,如果图中有(v,w)边,在线性
    序列中v就出现在w之前。
  • 拓扑排序广泛应用在依赖事件的排期上,还可以用在项目管理、数据库查询优化和矩阵乘法的次序优化上

拓扑排序的实现

  • 拓扑排序可以采用深度优先搜索DFS实现。
    • 将工作流程建立为图,工作项是节点依赖关系是有向边。工作流程图一定是个有向无环图DAG,否则出现循环依赖。
    • 对DAG图调用DFS算法,以得到每个顶点的“结束时间”,按照每个顶点的“结束时间”从大到小排序,输出这个次序下的顶点列表
  • 根据遍历次序的不同,拓扑排序的结果可能有多个

示例:

在这里插入图片描述

# 将工作流程建立为图
dfs_g = DFSGraph()
dfs_g.add_edge("3/4 cup milk", "1 cup mix")
dfs_g.add_edge("1 egg", "1 cup mix")
dfs_g.add_edge("1 tbl oil", "1 cup mix")
dfs_g.add_edge("1 cup mix", "pour 1/4 cup")
dfs_g.add_edge("1 cup mix", "heat syrup")
dfs_g.add_edge("heat griddle", "pour 1/4 cup")
dfs_g.add_edge("pour 1/4 cup", "turn when bubbly")
dfs_g.add_edge("turn when bubbly", "eat")
dfs_g.add_edge("heat syrup", "eat")dfs_g.dfs()
res = []
for i in dfs_g.vertexes.values():res.append((i.finish, i.key))
# 按照每个顶点的“结束时间”从大到小排序
res.sort(key=lambda x: x[0], reverse=True)
print("拓扑排序结果:", res)### 输出结果
拓扑排序结果: [(18, 'heat griddle'), (16, '1 tbl oil'), (14, '1 egg'), (12, '3/4 cup milk'), (11, '1 cup mix'), (10, 'heat syrup'), (8, 'pour 1/4 cup'), (7, 'turn when bubbly'), (6, 'eat')]

在这里插入图片描述

二、图的应用-强连通分支

强连通分支Strongly Connected Components

  • 强连通分支,定义为图G的一个子集C。C中的任意两个顶点v,w之间都有路径来回,即(v,w)(w,v)都是C的路径,而且C是具有这样性质的最大子集
  • Transposition转置:一个有向图G的转置GT,定义为将图G的所有边的顶点交换次序,如将(v,w)转换为(w,v)。图和转置图在强连通分支的数量和划分上,是相同的。
  • 常用强连通分支算法有Tarjan算法、Gabow算法(对Tarjan的改进)和Kosaraju算法,这些算法的基本思想是进行深度优先搜索,并通过标记来识别强连通分支。

在这里插入图片描述

寻找强连通分支(在图中发现高度聚集节点群)的应用

  • 网络分析
    • 在社交网络分析中,强连通分支可以帮助识别紧密联系的小团体或者社区。
    • 在通信网络中,强连通分支可用于优化路由策略,提高网络的稳定性和效率。
  • 算法设计:在算法设计中,特别是在有向图的处理算法中,例如拓扑排序,识别强连通分支可以简化问题,使得算法更加高效。
  • 系统建模:在系统动态和反馈系统分析中,强连通分支能够揭示系统内部各部分之间的相互作用和依赖关系。
  • 程序分析:在软件工程中,特别是在编译器的控制流分析中,强连通分支有助于理解程序中的循环结构,优化代码。
  • 经济学和博弈论:在经济学模型中,强连通分支可以用来分析市场中的不同参与者之间的相互作用和影响。
  • 生物信息学:在生物信息学中,可以通过分析蛋白质之间的相互作用网络,利用强连通分支来识别关键的生物分子和途径。
  • 数据挖掘:在数据挖掘中,识别大型数据库中的强连通分支有助于发现数据之间的深层次联系。

在这里插入图片描述

强连通分支算法-Kosaraju算法思路

  • 首先,对图G调用深度优先搜索DFS算法,为每个顶点计算“结束时间”;
  • 然后,将图G进行转置,得到GT;
  • 再对GT调用DFS算法,但在dfs函数中,对每个顶点的搜索循环里,要以顶点的“结束时间”倒序的顺序来搜索。
  • 每次DFS访问到的节点构成一个强连通分支

Kosaraju算法实现

  • DFSGraph类:
    • 更新dfs方法的形参,可以指定顶点的遍历次序;
    • 更新dfsvisit方法的形参,增加形参tmp记录顶点递归次序
### 更新后的DFSGraph类
class DFSGraph(Graph):def __init__(self):super().__init__()self.time = 0def dfs(self, keys_order=None):"""keys_order参数:可指定遍历顶点的次序"""# 初始化顶点颜色和前驱for v in self:v.set_color("white")v.set_pred(-1)# 遍历未访问的顶点if keys_order:for key in keys_order:v = self.vertexes.get(key)if v.get_color() == "white":scc = [] # 记录每个强连通分支self.dfsvisit(v, scc)print(scc)else:for v in self:if v.get_color() == "white":self.dfsvisit(v)def dfsvisit(self, start_v: Vertex, tmp=[]):tmp.append(start_v.key)start_v.set_color("gray")self.time += 1# 记录第几步访问到这个顶点start_v.discovery = self.timefor next_v in start_v.get_connections():# 递归访问未访问的顶点并记录前驱if next_v.get_color() == "white":next_v.set_pred(start_v)self.dfsvisit(next_v, tmp)start_v.set_color("black")self.time += 1# 记录在第几步完成了此顶点探索start_v.finish = self.time

强连通分支-示例

edges = [["A", "B"],["B", "C"],["B", "E"],["C", "C"],["C", "F"],["D", "B"],["D", "G"],["E", "D"],["E", "A"],["F", "H"],["G", "E"],["H", "I"],["I", "F"],
]
# 对图G调用DFS算法,为每个顶点计算“结束时间”
dfs_g = DFSGraph()
for i in edges:dfs_g.add_edge(i[0], i[1])
dfs_g.dfs()
res = []
for i in dfs_g.vertexes.values():res.append((i.finish, i.key))
res.sort(key=lambda x: x[0], reverse=True)  # “结束时间”从大到小排序
print("第一趟DFS按“结束时间”从大到小排序:")
print(res)
keys_order = [i[1] for i in res]### 输出结果
第一趟DFS按“结束时间”从大到小排序:
[(18, 'A'), (17, 'B'), (16, 'E'), (15, 'D'), (14, 'G'), (10, 'C'), (9, 'F'), (8, 'H'), (7, 'I')]

第一趟DFS

在这里插入图片描述

转置后第二趟DFS

# 按照第一步记录的完成时间逆序对反转图进行DFS
dfs_gt = DFSGraph()
for i in edges:dfs_gt.add_edge(i[1], i[0])
print("强连通分支如下:")
dfs_gt.dfs(keys_order)

在这里插入图片描述

强连通分支结果

### 输出结果
强连通分支如下:
['A', 'E', 'B', 'D', 'G']
['C']
['F', 'I', 'H']

在这里插入图片描述


您正在阅读的是《数据结构与算法Python版》专栏!关注不迷路~


http://www.mrgr.cn/news/82277.html

相关文章:

  • 计算机网络练习题
  • vue学习第一阶段
  • 【双指针】算法题(二)
  • python识别outlook邮件并且将pdf文件作为附件发送邮件
  • 光耦合器如何增强医疗设备的安全性
  • 植物活性长末端重复序列反转录转座子研究进展-文献精读95
  • chatwoot 开源客服系统搭建
  • 我的 2024 年终总结
  • 【信号滤波 (中)】采样条件及多种滤波算法对比(滑动平均/陷波滤波)
  • 【机器学习】工业 4.0 下机器学习如何驱动智能制造升级
  • JSON 系列之3:导入JSON标准示例数据
  • Redis - 1 ( 11000 字 Redis 入门级教程 )
  • SpringBoot整合Canal+RabbitMQ监听数据变更
  • gitlab的搭建及使用
  • uniapp H5 对接 声网,截图
  • 【Java回顾】 Day1简介-----变量命名规则
  • 时间序列预测算法---LSTM
  • Git的使用流程(详细教程)
  • Anaconda+PyTorch(CPU版)安装
  • net core介绍
  • 【0379】Postgres内核 walreceiver (libpqwalreceiver API)分析
  • 【面试AI算法题中的知识点】方向涉及:ML/DL/CV/NLP/大数据...本篇介绍Tensor RT 的优化流程。
  • FreeRTOS的队列
  • OpenCV-Python实战(13)——图像轮廓
  • UnityRenderStreaming使用记录(三)
  • 细说STM32F407单片机轮询方式CAN通信