Skip to content

Commit 8e33a16

Browse files
committed
✨ 增加了拓扑排序
1 parent 5b08ac8 commit 8e33a16

File tree

5 files changed

+281
-31
lines changed

5 files changed

+281
-31
lines changed

061 拓扑排序/egg.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""
2+
背景,假如你在用python开发游戏的任务系统
3+
这个任务系统必须是无环的,否则就出bug了。
4+
"""
5+
6+
# 拓扑图
7+
# 任务id:任务信息
8+
num2Task = {
9+
1: {
10+
"name": "开始冒险",
11+
"details": "前往风起之地",
12+
},
13+
2: {
14+
"name": "解救云隐村",
15+
"details": "帮助云隐村解决危机",
16+
},
17+
3: {
18+
"name": "破晓之星",
19+
"details": "追踪星银之路",
20+
},
21+
4: {
22+
"name": "征服风神",
23+
"details": "挑战风神巅峰",
24+
},
25+
5: {
26+
"name": "龙之末裔",
27+
"details": "揭开龙的秘密",
28+
},
29+
}
30+
31+
graph = {
32+
1: {2, 3},
33+
2: {4},
34+
3: {4},
35+
4: {5},
36+
5: {},
37+
}

061 拓扑排序/main.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
from graphlib import TopologicalSorter, CycleError
2+
3+
4+
def main():
5+
# test0()
6+
# test1()
7+
test3()
8+
...
9+
10+
11+
def test0():
12+
# 返回前驱为0的节点
13+
ts = TopologicalSorter({
14+
"D": {"B", "C"},
15+
"C": {"A"},
16+
"B": {"A"}
17+
})
18+
ts.prepare() # 先让它准备一下,看看有没有环
19+
print(ts.get_ready()) # 找到没有前驱的节点
20+
21+
22+
def test1():
23+
graph = {"D": {"B", "C"}, "C": {"A"}, "B": {"A"}}
24+
ts = TopologicalSorter(graph)
25+
c = ts.static_order()
26+
print(list(c)[::-1])
27+
28+
29+
def test2():
30+
try:
31+
ts2 = TopologicalSorter({
32+
'a': {'b'},
33+
'b': {'c'},
34+
'c': {'d'},
35+
'd': {'a'},
36+
})
37+
print(list(ts2.static_order()))
38+
except CycleError:
39+
...
40+
41+
42+
def test3():
43+
# 同样的图,换一个图的生成方式,用边生成
44+
ts = TopologicalSorter()
45+
ts.add('d', 'b')
46+
ts.add('d', 'c')
47+
ts.add('b', 'a')
48+
ts.add('c', 'a')
49+
print(list(ts.static_order()))
50+
...
51+
52+
53+
if __name__ == "__main__":
54+
"""
55+
自创编译系统检测引入是否合理
56+
工作流程管理
57+
58+
在游戏项目中:
59+
任务系统 关卡设计 任务进度解锁 效果触发
60+
61+
"""
62+
main()

061 拓扑排序/test.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
from typing import *
2+
3+
4+
def main():
5+
num2Task = {
6+
1: {
7+
"name": "构思",
8+
"details": ...,
9+
},
10+
2: {
11+
"name": "拍视频",
12+
"details": ...,
13+
},
14+
3: {
15+
"name": "找素材",
16+
"details": ...,
17+
},
18+
4: {
19+
"name": "剪辑",
20+
"details": ...,
21+
},
22+
5: {
23+
"name": "发b站",
24+
"details": ...,
25+
},
26+
}
27+
graph = {
28+
1: {2, 3},
29+
2: {4},
30+
3: {4},
31+
4: {5},
32+
5: {},
33+
}
34+
graph = {
35+
1: {2},
36+
2: {3},
37+
3: {1},
38+
}
39+
arr = f(graph)
40+
if len(arr) < len(graph):
41+
print("cycle")
42+
print()
43+
44+
45+
def f(graph: Dict[int, Set[int]]) -> List[int]:
46+
from collections import deque
47+
48+
count_dict = {n: 0 for n in graph}
49+
for node, child_set in graph.items():
50+
for child in child_set:
51+
count_dict[child] += 1
52+
53+
q = deque()
54+
for node, count in count_dict.items():
55+
if count == 0:
56+
q.append(node)
57+
58+
res = []
59+
while q:
60+
n = q.popleft()
61+
res.append(n)
62+
child_set = graph[n]
63+
for child in child_set:
64+
count_dict[child] -= 1
65+
if count_dict[child] == 0:
66+
q.append(child)
67+
return res
68+
69+
70+
if __name__ == '__main__':
71+
main()

061 拓扑排序/tradition.py

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
"""
2+
拓扑排序的传统实现
3+
4+
"""
5+
6+
7+
def topological_sort(graph):
8+
def dfs(node):
9+
visited[node] = True
10+
for child in graph[node]:
11+
if not visited[child]:
12+
dfs(child)
13+
result.append(node)
14+
15+
# 初始化
16+
visited = {node: False for node in graph}
17+
result = []
18+
19+
# 遍历图中的每个节点
20+
for node in graph:
21+
if not visited[node]:
22+
dfs(node)
23+
24+
# 结果是逆序的,反转得到拓扑排序
25+
return result[::-1]
26+
27+
28+
def f(graph):
29+
# 记录所有的入度量
30+
from collections import deque
31+
count_graph = {n: 0 for n in graph}
32+
for k, child_set in graph.items():
33+
for child in child_set:
34+
count_graph[child] += 1
35+
# 所有入度为0的节点入队列
36+
q = deque()
37+
for node, count in count_graph.items():
38+
if count == 0:
39+
q.append(node)
40+
res = []
41+
# 准备好开始队列了
42+
while q:
43+
n = q.popleft()
44+
res.append(n)
45+
child_set = graph[n]
46+
for child in child_set:
47+
count_graph[child] -= 1
48+
if count_graph[child] == 0:
49+
q.append(child)
50+
return res
51+
52+
53+
def topological_sort_no_cycle(graph):
54+
# 能检测出是否有环的情况
55+
def dfs(node):
56+
visited[node] = True
57+
currently_visiting.add(node)
58+
59+
for child in graph[node]:
60+
if not visited[child]:
61+
if dfs(child):
62+
return True
63+
elif child in currently_visiting:
64+
# 如果在当前DFS路径上发现已经访问过的节点,说明存在环
65+
return True
66+
67+
currently_visiting.remove(node)
68+
result.append(node)
69+
return False
70+
71+
# 初始化
72+
visited = {node: False for node in graph}
73+
result = []
74+
currently_visiting = set()
75+
76+
# 遍历图中的每个节点
77+
for node in graph:
78+
if not visited[node]:
79+
if dfs(node):
80+
# 如果在DFS中发现环,返回空列表表示拓扑排序不可行
81+
return []
82+
83+
# 结果是逆序的,反转得到拓扑排序
84+
return result[::-1]
85+
86+
87+
def main():
88+
# 示例用法
89+
graph = {
90+
1: {2, 3},
91+
2: {4},
92+
3: {4, 5},
93+
4: {5},
94+
5: {},
95+
}
96+
g = {
97+
1: {2},
98+
2: {3},
99+
3: {4},
100+
4: {5},
101+
5: {1},
102+
}
103+
104+
# result = topological_sort_no_cycle(graph)
105+
# result = topological_sort(g)
106+
result = f(graph)
107+
print("Topological Sort:", result)
108+
109+
110+
if __name__ == '__main__':
111+
main()

视频还没录但计划的/058 用内置库实现拓扑排序/main.py

Lines changed: 0 additions & 31 deletions
This file was deleted.

0 commit comments

Comments
 (0)