给出一个元组列表,我需要从该列表中找到所有唯一路径:
输入:[('a','b'),('b','c'),('c','d'),('g','i'),('d','e'),('e','f'),('f','g'),('c','g')]
输出:[['a','b','c','d','e','f','g'],['a','b','c','g','i']]
(2种可能的唯一路径)
如果元组的第二个元素与另一个元组的第一个元素匹配,则两个元组可以连接,即:一个元组为(_,a)
,其他元组为(a,_)
。
这个问题已经在这里提出:Getting Unique Paths from list of tuple,但是该解决方案是在haskell中实现的(我对此语言一无所知)。
但是您知道Python是否有有效的方法吗?
我知道库itertools
具有许多高效的内置函数来处理类似的事情,但是我对此不太熟悉。
答案 0 :(得分:1)
您要在图形中查找所有simple paths。
Python有一个很棒的图形处理库:networkx。您可以使用几行代码来解决您的问题:
import networkx as nx
a = [('a','b'),('b','c'),('c','d'),('g','i'),('d','e'),('e','f'),('f','g'),('c','g')]
# Create graph
G = nx.Graph()
# Fill graph with data
G.add_edges_from(a)
# Get all simple paths from node 'a' to node 'i'
list(nx.all_simple_paths(G, 'a', 'i'))
将返回您
[['a', 'b', 'c', 'g', 'i'], ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'i']]
如果要使用所有可能的路径,只需将其替换为最后一行:
for start in G.nodes:
for end in G.nodes:
if start != end:
print(list(nx.all_simple_paths(G, start, end)))
答案 1 :(得分:1)
您可以构建一个将每个父节点映射到已连接子节点列表的字典,以便您可以平均时间复杂度为 O(n):<< / p>
def get_paths(parent, mapping):
if parent not in mapping:
yield [parent]
return
for child in mapping[parent]:
for path in get_paths(child, mapping):
yield [parent, *path]
edges = [('a','b'),('b','c'),('c','d'),('g','i'),('d','e'),('e','f'),('f','g'),('c','g')]
parents = set()
children = set()
mapping = {}
for a, b in edges:
mapping.setdefault(a, []).append(b)
parents.add(a)
children.add(b)
print([path for parent in parents - children for path in get_paths(parent, mapping)])
这将输出:
[['a', 'b', 'c', 'd', 'e', 'f', 'g', 'i'], ['a', 'b', 'c', 'g', 'i']]
答案 2 :(得分:0)
您可以将递归与生成器一起使用:
d = [('a','b'),('b','c'),('c','d'),('g','i'),('d','e'),('e','f'),('f','g'),('c','g')]
def get_paths(start, c = []):
r = [b for a, b in d if a == start]
if r:
for i in r:
yield from get_paths(i, c+[i])
else:
yield c
print(list(get_paths('a', ['a'])))
输出:
[['a', 'b', 'c', 'd', 'e', 'f', 'g', 'i'], ['a', 'b', 'c', 'g', 'i']]