《python算法教程》Day4 - 拓扑排序(基于有向无环图)
2018-04-15 本文已影响31人
billyang916
这是《python算法教程》的第4篇读书笔记。这篇笔记的主要内容为拓扑排序。
拓扑排序简介
在将一件事情分解为若干个小事情时,会发现小事情之间有完成的先后次序之分,若不按照特定的顺序完成,则会使得整件事情无法完成。因此这需要获取工作安排表。而拓扑排则怎能根据小事情之间的先后次序生成这样一个工作安排表(拓扑序列)。但请注意,能满足要求的拓扑序列不止一个。
代码实例
下图是用于拓扑排序的图。
以下是代码的实现过程,请注意,由于这是有向图,所以邻接字典做了特殊的约定,每一个节点所能访问到的节点(直接或间接)均显示在该节点的集合中
#朴素拓扑排序
#G为邻接字典
def naiveTopoSort(G,S=None):
if S is None:
S=set(G.keys())
if len(S)==1:
return list(S)
s=S.pop()
seq=naiveTopoSort(G,S)
minIdx=0
for i,v in enumerate(seq):
if s in G[v]:
minIdx=i+1
seq.insert(minIdx,s)
return seq
#有向无环图的邻接字典
G={
'a':{'b''c','d','e','f'},
'b':{'c','d','e','f'},
'c':{'d','e','f'},
'd':{'e','f'},
'e':{'f'},
'f':{}
}
res=naiveTopoSort(G)
print(res)
以下为不适用递归的拓扑排序
#使用循环进行拓扑排序
def topoSort(G):
#初始化计算被指向节点的字典
cnt=dict((u,0) for u in G.keys())
#若某节点被其他节点指向,该节点计算量+1
for u in G:
for v in G[u]:
cnt[v]+=1
#收集被指向数为0的节点,此时Q只有一个节点,即起始节点a
Q=[u for u in cnt.keys() if cnt[u]==0]
#记录结果
seq=[]
while Q:
s=Q.pop()
seq.append(s)
for u in G[s]:
cnt[u]-=1
if cnt[u]==0:
Q.append(u)
return seq
#有向无环图的邻接字典
G={
'a':{'b','f'},
'b':{'c','d','f'},
'c':{'d'},
'd':{'e','f'},
'e':{'f'},
'f':{}
}
res=topoSort(G)
print(res)