当前位置:
首页 > Python基础教程 >
-
python实现拓扑排序的基本教程
拓扑排序是针对有向无环图(DAG, Directed Acyclic Graph)的一种排序方式,它会把图中的顶点排成一个线性序列,使得对于任意一条从顶点 $ u $ 到顶点 $ v $ 的有向边 $ (u, v) $,顶点 $ u $ 在序列中都出现在顶点 $ v $ 的前面。这种排序不是唯一的,因为图中可能存在多个这样的序列。
在Python中实现拓扑排序,常用的方法有两种:
1. **使用Kahn算法**:基于入度的概念,每次移除图中入度为0的顶点,并将其添加到结果序列中,同时减少其邻接顶点的入度。
2. **使用深度优先搜索(DFS)**:通过DFS遍历图,并在回溯时将顶点添加到结果序列的开头(或尾部,取决于具体实现)。
### 使用Kahn算法实现拓扑排序
这里提供一个使用Kahn算法的拓扑排序Python实现示例:
### 使用DFS实现拓扑排序
使用DFS的拓扑排序稍微复杂一些,但原理上是在DFS过程中记录每个节点访问完成的时刻,并按照这些时刻的逆序排列所有节点。这里提供一个简化的版本,直接在DFS中反转添加节点到结果列表:
注意,这两个实现都假设了输入的图是无环的。如果图中存在环,则拓扑排序不存在,上述实现可能无法给出明确的错误提示(尽管在某些情况下,如Kahn算法,可以通过检查排序后的节点数是否与原图节点数相同来间接检测环的存在)。
在Python中实现拓扑排序,常用的方法有两种:
1. **使用Kahn算法**:基于入度的概念,每次移除图中入度为0的顶点,并将其添加到结果序列中,同时减少其邻接顶点的入度。
2. **使用深度优先搜索(DFS)**:通过DFS遍历图,并在回溯时将顶点添加到结果序列的开头(或尾部,取决于具体实现)。
### 使用Kahn算法实现拓扑排序
这里提供一个使用Kahn算法的拓扑排序Python实现示例:
from collections import deque, defaultdict
def topological_sort_kahn(graph):
# 获取图中所有顶点的入度
in_degree = defaultdict(int)
for node in graph:
for neighbor in graph[node]:
in_degree[neighbor] += 1
# 收集所有入度为0的节点
queue = deque([node for node in graph if in_degree[node] == 0])
top_order = []
# 当队列非空时继续
while queue:
node = queue.popleft()
top_order.append(node)
# 减少当前节点所有邻接节点的入度
for neighbor in graph[node]:
in_degree[neighbor] -= 1
if in_degree[neighbor] == 0:
queue.append(neighbor)
# 如果排序后的顶点数不等于图中的顶点数,则图中存在环
if len(top_order) == len(graph):
return top_order
else:
return None # 或者抛出一个异常
# 示例图,使用邻接表表示
graph = {
'A': ['B', 'C'],
'B': ['D'],
'C': ['D'],
'D': []
}
print(topological_sort_kahn(graph))
def topological_sort_kahn(graph):
# 获取图中所有顶点的入度
in_degree = defaultdict(int)
for node in graph:
for neighbor in graph[node]:
in_degree[neighbor] += 1
# 收集所有入度为0的节点
queue = deque([node for node in graph if in_degree[node] == 0])
top_order = []
# 当队列非空时继续
while queue:
node = queue.popleft()
top_order.append(node)
# 减少当前节点所有邻接节点的入度
for neighbor in graph[node]:
in_degree[neighbor] -= 1
if in_degree[neighbor] == 0:
queue.append(neighbor)
# 如果排序后的顶点数不等于图中的顶点数,则图中存在环
if len(top_order) == len(graph):
return top_order
else:
return None # 或者抛出一个异常
# 示例图,使用邻接表表示
graph = {
'A': ['B', 'C'],
'B': ['D'],
'C': ['D'],
'D': []
}
print(topological_sort_kahn(graph))
### 使用DFS实现拓扑排序
使用DFS的拓扑排序稍微复杂一些,但原理上是在DFS过程中记录每个节点访问完成的时刻,并按照这些时刻的逆序排列所有节点。这里提供一个简化的版本,直接在DFS中反转添加节点到结果列表:
from collections import defaultdict, deque
def topological_sort_dfs(graph):
visited = set()
stack = []
def dfs(node):
if node in visited:
return
visited.add(node)
for neighbor in graph.get(node, []):
dfs(neighbor)
stack.append(node)
for node in graph:
if node not in visited:
dfs(node)
# 弹出顺序即为拓扑排序的结果(栈是后入先出)
return stack[::-1]
# 示例图,使用邻接表表示
graph = {
'A': ['B', 'C'],
'B': ['D'],
'C': ['D'],
'D': []
}
print(topological_sort_dfs(graph))
def topological_sort_dfs(graph):
visited = set()
stack = []
def dfs(node):
if node in visited:
return
visited.add(node)
for neighbor in graph.get(node, []):
dfs(neighbor)
stack.append(node)
for node in graph:
if node not in visited:
dfs(node)
# 弹出顺序即为拓扑排序的结果(栈是后入先出)
return stack[::-1]
# 示例图,使用邻接表表示
graph = {
'A': ['B', 'C'],
'B': ['D'],
'C': ['D'],
'D': []
}
print(topological_sort_dfs(graph))
注意,这两个实现都假设了输入的图是无环的。如果图中存在环,则拓扑排序不存在,上述实现可能无法给出明确的错误提示(尽管在某些情况下,如Kahn算法,可以通过检查排序后的节点数是否与原图节点数相同来间接检测环的存在)。
最后,如果你对python语言还有任何疑问或者需要进一步的帮助,请访问https://www.xin3721.com 本站原创,转载请注明出处:https://www.xin3721.com/Python/python50247.html
栏目列表
最新更新
求1000阶乘的结果末尾有多少个0
详解MyBatis延迟加载是如何实现的
IDEA 控制台中文乱码4种解决方案
SpringBoot中版本兼容性处理的实现示例
Spring的IOC解决程序耦合的实现
详解Spring多数据源如何切换
Java报错:UnsupportedOperationException in Col
使用Spring Batch实现批处理任务的详细教程
java中怎么将多个音频文件拼接合成一个
SpringBoot整合ES多个精确值查询 terms功能实
SQL Server 中的数据类型隐式转换问题
SQL Server中T-SQL 数据类型转换详解
sqlserver 数据类型转换小实验
SQL Server数据类型转换方法
SQL Server 2017无法连接到服务器的问题解决
SQLServer地址搜索性能优化
Sql Server查询性能优化之不可小觑的书签查
SQL Server数据库的高性能优化经验总结
SQL SERVER性能优化综述(很好的总结,不要错
开启SQLSERVER数据库缓存依赖优化网站性能
uniapp/H5 获取手机桌面壁纸 (静态壁纸)
[前端] DNS解析与优化
为什么在js中需要添加addEventListener()?
JS模块化系统
js通过Object.defineProperty() 定义和控制对象
这是目前我见过最好的跨域解决方案!
减少回流与重绘
减少回流与重绘
如何使用KrpanoToolJS在浏览器切图
performance.now() 与 Date.now() 对比