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