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

Python 从元组列表生成所有可能的路径,python,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个可能的唯一路径) 如果元组的第二个元素与另一个元组的第一个元素匹配,则两个元组可以连接,即:一个元组是(\uu,a),另一个元组类似(a,) 这里已经提出了这个问

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

输入:
[('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个可能的唯一路径)

如果元组的第二个元素与另一个元组的第一个元素匹配,则两个元组可以连接,即:一个元组是
(\uu,a)
,另一个元组类似
(a,)

这里已经提出了这个问题:但是解决方案是用haskell实现的(我对这种语言一无所知)

但是您知道Python中是否有一种有效的方法来实现这一点吗?

我知道库
itertools
中有许多高效的内置函数用于类似的东西,但我对此不太熟悉。

您希望在图表中找到所有函数

Python有一个惊人的图形处理库:。您可以通过几行代码来解决问题:

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'))
将返回给您:


如果需要所有可能的路径,只需将最后一行替换为:

for start in G.nodes:
    for end in G.nodes:
        if start != end:
            print(list(nx.all_simple_paths(G, start, end)))

您可以构建一个dict,将每个父节点映射到一个连接的子节点列表,这样您就可以递归地以O(n)的平均时间复杂度生成来自每个父节点的路径:

这将产生:

[['a', 'b', 'c', 'd', 'e', 'f', 'g', 'i'], ['a', 'b', 'c', 'g', 'i']]

可以对生成器使用递归:

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

你能分享一下你试图解决的问题吗?可能是一份非常感谢:)但在你的解决方案中,你假设“a”和“我”必然是你可能路径的开始和结束(在我的问题中,我对我的路径如何开始和结束没有任何假设,我只知道它们应该如何构建)。但我想我可以生成所有可能的路径,只需生成所有(开始/结束)组合,然后对每个组合应用您的方法(可能很长)即可更新答案。请注意,通过调用
nx更新的答案。所有节点上嵌套循环中的所有简单路径将解决方案转换为O(n^3)请注意,在每次递归调用中必须遍历所有节点,使得此解决方案的平均时间复杂度为O(n^2)。它还需要事先知道起始节点,这并不是这个问题的输入。@b您如何推导出
O(n^2)
O(n)
?您的字典查找是
O(n)
,但是如果在
for
循环中递归调用,最坏的结果是
=O(2^n)
(对于我的也是如此)。字典查找平均花费O(1),而不是O(n),而在所有节点中使用
[b表示a,b表示d,如果a==start]
对给定父节点进行线性搜索则花费O(n)。递归调用以线性方式遍历所有节点,因此我的解决方案的成本为O(n),而您的解决方案的成本为O(n^2)。然而,另一个因素是发散路径的数量,当父节点有多个子节点时会发生发散路径,如果这个数量很大,那么我的解决方案将花费O(n x m),而你的解决方案将花费O(n^2 x m),其中,
n
是节点数,
m
是发散路径数。@b我的答案包含额外的传递
d
,但再加上递归调用的线性时间复杂度,结果不是
O(n)+O(n)=>O(n)
?循环外的额外线性传递不会增加
n
的功率。不,您在每个递归调用中迭代所有节点的长度,并且递归调用至少完成节点数的次数,因此会导致
n
n
步数。在dict中查找一个节点,就不需要在每次递归调用中迭代所有节点,因此我的解决方案就不需要O(n)复杂度。
[['a', 'b', 'c', 'd', 'e', 'f', 'g', 'i'], ['a', 'b', 'c', 'g', 'i']]