您的问题被称为topological sort,来自维基百科:
在计算机科学领域,拓扑排序或拓扑
有向图的排序是其顶点的线性排序,例如
对于从顶点 u 到顶点 v 的每条有向边 uv,u 来
顺序中的 v 之前。
在您的特定情况下,图的顶点是包,边是依赖项。您可以使用Kahn's algorithm(无递归)解决问题,实现如下:
def toposort(graph):
# init the indegree for each noe
nodes = graph.keys() | set([node for adjacents in graph.values() for node in adjacents])
in_degree = {node: 0 for node in nodes}
# compute the indegree
for k, adjacents in graph.items():
for node in adjacents:
in_degree[node] += 1
# init the heap with the nodes with indegree 0 and priority given by key
heap = [node for node, degree in in_degree.items() if degree == 0]
top_order = []
while heap: # heap is not empty
node = heap.pop() # get the element with highest priority and remove from heap
top_order.append(node) # add to topological order
for adjacent in graph.get(node, []): # iter over the neighbors of the node
in_degree[adjacent] -= 1
if in_degree[adjacent] == 0: # if the node has in_degree 0 add to the heap with priority given by key
heap.append(adjacent)
return top_order
packages = {'B7': ['R3'],
'R3': ['timestmp', 'Abbot', '9K'],
'tempor': ['cavie', 'sandals', 'B7'],
'Abbot': ['Duns'],
'timestmp': [],
'Duns': []}
reverse = {}
for key, nodes in packages.items():
for node in nodes:
reverse.setdefault(node, []).append(key)
print(toposort(reverse))
输出
['timestmp', '9K', 'sandals', 'Duns', 'Abbot', 'R3', 'B7', 'cavie', 'tempor']
注意
为了使提议的解决方案起作用,它需要反转图,这就是以下几行的作用:
reverse = {}
for key, nodes in packages.items():
for node in nodes:
reverse.setdefault(node, []).append(key)
另请注意,顺序不是唯一的,例如在您的示例中,'timestmp' 和 'Duns' 都可能是第一个要安装的包,因为它们没有任何依赖项。
进一步