我正在尝试对Python中的唯一边列表进行排序,这样排序就会根据前一个边缘列出边缘列表,这个边缘具有与下一个边缘共享的顶点。我已经有了一个功能来获得“开始”和“结束”边缘。
例如,未排序的边列表就是:
[[0, 5], [2, 4], [4, 5], [1, 2], [0, 6]]
正确排序,这将如下:
[[6, 0], [0, 5], [4, 5], [2, 4], [1, 2]]
,[6,0]是起始边,[1,2]是结束边。
根据我看到的排序方法,排序是基于知道要排序的列表中的哪个索引来完成的,但在这种情况下,索引可以是0或1。
答案 0 :(得分:1)
from collections import defaultdict
followed_by = defaultdict(list)
def follows(edge1, edge2): # does edge2 follow edge1
return edge1 != edge2 and not set(edge1).isdisjoint(set(edge2))
def sorted_path(path, end):
start = path[-1]
for follower in followed_by[tuple(start)]:
if follower in path:
continue # avoid circularities
if follower == end:
return path + [end] # solution found
new_path = sorted_path(path + [follower], end) # recurse
if new_path:
return new_path # solution found
return None # solution not found
# build defaultdict of who follows who
for edge in edges:
for potential_follower in edges:
if follows(edge, potential_follower):
followed_by[tuple(edge)].append(potential_follower)
edges = [[0, 5], [2, 4], [4, 5], [1, 2], [0, 6]]
START = [0, 6]
END = [1, 2]
print(sorted_path([START], END)) # pass the path so far and terminal node
答案 1 :(得分:0)
我将对输入做一些假设:
鉴于这些假设,我要做的第一件事就是将输入转换为frozenset 1 以便能够利用散列:
edges = [frozenset(edge) for edge in edges]
现在我构建一个从节点到边缘的映射:
from collections import defaultdict
nodes_to_edges = defaultdict(set)
for edge in edges:
for node in edge:
nodes_to_edges[node].add(edge)
nodes_to_edges.default_factory = None
现在,路径是通过遍历nodes_to_edges
来定义的。在这里,我将手动设置起始节点,因为你知道它。如果您不知道起始节点,则可以在nodes_to_edges
中找到一个密钥,其中包含的集合的长度为1。将有2个这样的键(起始节点和结束节点),但如果图形是无向的,那么你可以遍历任何一种方式,它没有任何区别:
current_node = 6
path = []
while nodes_to_edges:
edge = nodes_to_edges[current_node].pop()
assert not nodes_to_edges[current_node]
del nodes_to_edges[current_node]
path.append(edge)
next_node = next(iter(edge - {current_node}))
next_edges = nodes_to_edges[next_node]
if len(next_edges) == 1: # End node.
del nodes_to_edges[next_node]
else:
next_edges.remove(edge)
current_node = next_node
当您考虑这种实现时,请记住几个不变量:
nodes_to_edges
两次。因此,对于我们添加到path
的每个边缘,我们需要从nodes_to_edges
中删除两个。break
子句中添加else
语句来摆脱 iff 以上的第三个假设。我认为这也可能有点放松第二个假设 - 新的假设是没有节点有超过2个边连接到它。1 我使用了冻结集,因为它看起来像是在使用无向边。如果边缘是定向的,则需要修改它以使用元组。
答案 2 :(得分:0)
以下代码不是一种有效的方法,但完成了您的示例。在这个意义上,独特解决方案的假设被理解为“独特的边缘”。
lst = [[0, 5], [2, 4], [4, 5], [1, 2], [0, 6]]
l=len(lst)
#Your function gives ini and end:
ini = [0, 6]
end = [1, 2]
sol = [ini]
lst.remove(ini)
lst.remove(end)
while len(sol) < l - 1:
for x in lst:
if any(y in x for y in sol[-1]):
sol.append(x)
lst.remove(sol[-1])
break
sol.append(end)
print("sol", sol)