Skip to content

Commit 4688815

Browse files
committed
更新拓扑排序代码模版
1 parent 2f43b6d commit 4688815

File tree

2 files changed

+80
-16
lines changed

2 files changed

+80
-16
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import collections
2+
3+
class Solution:
4+
# 拓扑排序,graph 中包含所有顶点的有向边关系(包括无边顶点)
5+
def topologicalSortingDFS(self, graph: dict):
6+
visited = set() # 记录当前顶点是否被访问过
7+
onStack = set() # 记录同一次深搜时,当前顶点是否被访问过
8+
order = [] # 用于存储拓扑序列
9+
hasCycle = False # 用于判断是否存在环
10+
11+
def dfs(u):
12+
nonlocal hasCycle
13+
if u in onStack: # 同一次深度优先搜索时,当前顶点被访问过,说明存在环
14+
hasCycle = True
15+
if u in visited or hasCycle: # 当前节点被访问或者有环时直接返回
16+
return
17+
18+
visited.add(u) # 标记节点被访问
19+
onStack.add(u) # 标记本次深搜时,当前顶点被访问
20+
21+
for v in graph[u]: # 遍历顶点 u 的邻接顶点 v
22+
dfs(v) # 递归访问节点 v
23+
24+
order.append(u) # 后序遍历顺序访问节点 u
25+
onStack.remove(u) # 取消本次深搜时的 顶点访问标记
26+
27+
for u in graph:
28+
if u not in visited:
29+
dfs(u) # 递归遍历未访问节点 u
30+
31+
if hasCycle: # 判断是否存在环
32+
return [] # 存在环,无法构成拓扑序列
33+
order.reverse() # 将后序遍历转为拓扑排序顺序
34+
return order # 返回拓扑序列
35+
36+
def findOrder(self, n: int, edges):
37+
# 构建图
38+
graph = dict()
39+
for i in range(n):
40+
graph[i] = []
41+
for v, u in edges:
42+
graph[u].append(v)
43+
44+
return self.topologicalSortingDFS(graph)
45+
46+
print(Solution().findOrder(2, [[1,0]]))
47+
print(Solution().findOrder(4, [[1,0],[2,0],[3,1],[3,2]]))
48+
print(Solution().findOrder(1, []))
Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,41 @@
11
import collections
22

3-
class solution:
4-
def topologicalSorting(graph):
5-
indegrees = {u: 0 for u in graph}
3+
class Solution:
4+
# 拓扑排序,graph 中包含所有顶点的有向边关系(包括无边顶点)
5+
def topologicalSortingKahn(self, graph: dict):
6+
indegrees = {u: 0 for u in graph} # indegrees 用于记录所有节点入度
67
for u in graph:
78
for v in graph[u]:
8-
indegrees[v] += 1
9-
9+
indegrees[v] += 1 # 统计所有节点入度
1010

11+
# 将入度为 0 的顶点存入集合 S 中
1112
S = collections.deque([u for u in indegrees if indegrees[u] == 0])
12-
order = []
13+
order = [] # order 用于存储拓扑序列
1314

1415
while S:
15-
u = S.pop()
16-
order.append(u)
17-
for v in graph[u]:
18-
indegrees[v] -= 1
19-
if indegrees[v] == 0:
20-
S.append(v)
16+
u = S.pop() # 从集合中选择一个没有前驱的顶点 0
17+
order.append(u) # 将其输出到拓扑序列 order 中
18+
for v in graph[u]: # 遍历顶点 u 的邻接顶点 v
19+
indegrees[v] -= 1 # 删除从顶点 u 出发的有向边
20+
if indegrees[v] == 0: # 如果删除该边后顶点 v 的入度变为 0
21+
S.append(v) # 将其放入集合 S 中
2122

22-
size = len(indegrees)
23-
if size == len(S):
24-
return order
25-
return None
23+
if len(indegrees) != len(order): # 还有顶点未遍历(存在环),无法构成拓扑序列
24+
return []
25+
return order # 返回拓扑序列
26+
27+
28+
def findOrder(self, n: int, edges):
29+
# 构建图
30+
graph = dict()
31+
for i in range(n):
32+
graph[i] = []
33+
34+
for u, v in edges:
35+
graph[u].append(v)
36+
37+
return self.topologicalSortingKahn(graph)
38+
39+
print(Solution().findOrder(2, [[1,0]]))
40+
print(Solution().findOrder(4, [[1,0],[2,0],[3,1],[3,2]]))
41+
print(Solution().findOrder(1, []))

0 commit comments

Comments
 (0)