从元组列表生成所有可能的路径

时间:2019-05-15 13:24:51

标签: python

给出一个元组列表,我需要从该列表中找到所有唯一路径:

输入:[('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具有许多高效的内置函数来处理类似的事情,但是我对此不太熟悉。

3 个答案:

答案 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']]