Python中的边排序列表
我试图在Python中对唯一边的列表进行排序,这样排序就可以根据前一条边与下一条边具有共享顶点的顺序排列边的列表。我已经有了一个函数来获取“开始”和“结束”边 例如,未排序的边列表如下所示:Python中的边排序列表,python,sorting,graph,Python,Sorting,Graph,我试图在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, 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。我将对输入进行一些假设:
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
现在,路径是通过遍历节点到边来定义的。在这里,我将手动设置开始节点,因为您知道它。如果不知道起始节点,可以在节点到边中找到其包含的集长度为1的键。将有两个这样的关键点(开始节点和结束节点),但如果图形是无向的,则您可以通过任意一种方式进行遍历,并且没有任何区别:
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
在考虑此实现时,请记住几个不变量:
- 每个边在节点到边中存在两次。因此,对于我们添加到
路径
的每一条边,我们需要从节点到边
删除两条边
- 我们可以通过在
else
子句中添加一个break
语句来摆脱上面的第三个假设,前提是您知道start节点。我认为这可能也放松了第二个假设——新的假设是没有节点连接超过2条边
1我使用了冻结集,因为它看起来像是在使用无向边。如果边是定向的,您需要修改它以使用元组。下面的代码不是一种有效的方法,但完成了您的示例。唯一解的假设被用来理解这个意义上的“唯一边”
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)
lst=[[0,5]、[2,4]、[4,5]、[1,2]、[0,6]]
l=len(lst)
#您的函数提供ini和end:
ini=[0,6]
结束=[1,2]
sol=[ini]
第一次删除(ini)
一、拆除(完)
而len(sol)
如果输入是[[0,1],[0,2],[0,3],[1,2],[1,3],[2,3],
,那么预期的输出是什么?@ColinBasnett如果我理解正确,列表的开始和结束是预先指定的,列表的中间是从开始到结束必须采取的边缘路线基本上你所做的不是排序。这是一种寻路。排序是通过多次断言两个项目的顺序来完成的。如果你不能在不看其他物品的情况下确定两件物品的顺序,那么这就不是排序。是正确的,这不是排序,而是路径查找。我认为我们需要更多地了解奇数输入的预期输出。那么像这样的输入集呢:[[0,1],[1,2],[9,10]
。输出列表中是否需要[9,10]
,即使它是脱节的?那么[[0,1],[0,2],[0,3]
呢?@Kevin我已经设置了它,这样就不会有基于边顶点的不明确路径,这些边顶点设置了一条具有唯一标识符的曲线。你的案子不会发生。顶点最多在边中出现两次。起点和终点顶点仅显示一次。
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)