我有一个数据集,它是有向无环图(DAG)的特例。我的DAG中的节点有0或1个弧。所有弧都是相等加权的(也就是说,弧中包含的唯一信息是它指向的节点,没有“距离”或“成本”或“权重”)。
我的用户将以半随机顺序输入节点,期望保留无弧节点的顺序,但所有弧在指向它们的节点之前进行排序(因此以子项排序)。
这是一个表示我的数据的简化类:
class Node:
def __init__(self, name, arc=None):
self.name = str(name)
self.arc = str(arc)
(注意self.arc
是指向节点的字符串表示,而不是对象本身)
所以,给出这样的输入:
input = [Node('A'),
Node('B'),
Node('C'),
Node('Z', 'Y'),
Node('X', 'W'),
Node('Y', 'X'),
Node('W')]
你会得到这样的输出,最好使用最少的循环和中间数据结构:
output = [Node('A'),
Node('B'),
Node('C'),
Node('W'),
Node('X', 'W'),
Node('Y', 'X'),
Node('Z', 'Y')]
答案 0 :(得分:0)
到目前为止,这是我能够提出的最佳算法:
def topo_sort(nodes):
objects = {} # maps node names back to node objects
graph = OrderedDict() # maps node names to arc names
output = []
for node in nodes:
objects[node.name] = node
graph[node.name] = node.arc
arcs = graph.values()
# optional
missing = set(arcs) - set(graph) - {None}
if missing:
print('Invalid arcs: {}'.format(', '.join(missing)))
def walk(arc):
"""Recurse down the tree from root to leaf nodes."""
obj = objects.get(arc)
if obj and obj not in output:
follow_the_arcs(graph.get(arc))
output.append(obj)
# Find all root nodes
for node in graph:
if node not in arcs:
walk(node)
return ordered
我喜欢的是,只有2个循环(一个用于构建图形,一个用于查找根),输出仅使用list.append()
构建,没有慢list.insert()
个。任何人都可以想到对此有任何改进吗?我忽略了任何明显的低效率?
谢谢!