我有以下图表(相应的边缘值写在括号中):
L0 -> L1 ('01')
L1 -> L2 ('12')
L1 -> L4 ('14')
L4 -> L5 ('45')
L2 -> L3 ('23')
L3 -> L1 ('31')
现在我想要从L0
开始的一定长度的所有可能路径的边缘值列表。所以,如果length = 3
(不包括起始节点),我应该得到两个列表:
['01', '12', '23'] and ['01', '14', '45'].
允许遍历一个循环。我尝试使用2级字典来表示图形。
graph = {'L0': {'L1': '01'}, 'L1': {'L2': '12', 'L4': '14'}, 'L2': {'L3': '23'}, 'L3': {'L1': '31'}, 'L4': {'L5': '45'}}
def find_path(graph, start, depth):
k = 0
while k < depth:
a = graph[start]
for node in graph[start]:
start = node
path.append(a[node])
k+=1
return path
print find_path(graph, 'L0', 4)
显然它提供了一种可能的路径输出。但我想要所有可能的。
答案 0 :(得分:2)
我会以递归方式进一步推进,直到达到限制或无法继续进展。
# graph: Graph we are operating on
# node: Node we are starting from
# hops: Number of hops we can still do (edges we can take)
def findPaths(graph, node, hops):
# if no further hops should be done, we were successful and
# can end the recursion
if hops == 0:
yield []
return
# if the node is not in the graph, we cannot go further, so
# the current path is invalid
if node not in graph:
return
# for every node we can reach from the current
for n in graph[node]:
# find all paths we can take from here
for path in findPaths(graph, n, hops - 1):
# and concat the edge names
yield [graph[node][n]] + path
在你的图表上使用(在给定的表示中),这给出了:
>>> list(findPaths(graph, 'L0', 3))
[['01', '14', '45'], ['01', '12', '23']]
>>> list(findPaths(graph, 'L0', 4))
[['01', '12', '23', '31']]
>>> list(findPaths(graph, 'L0', 2))
[['01', '14'], ['01', '12']]
答案 1 :(得分:1)
我将其表示为一个简单的edge:edge
词典:
links = {
0: [1],
1: [2, 4],
2: [3],
4: [5],
3: [1]
}
然后你可以迭代它:
def get_all_paths(links, length, start=0):
paths = [[start]]
for i in range(length):
newpaths = []
for path in paths:
try:
for next_node in links[path[-1]]:
newpaths.append(path + [next_node])
except KeyError:
pass
paths = newpaths
return paths
get_all_paths(links, 3)
#>>> [[0, 1, 2, 3], [0, 1, 4, 5]]
每个[0, 1, 2, 3]
到[(0,1), (1,2), (2,3)]
的转换可以在单独的步骤中完成。
它也适用于你的图表:
links = {'L0': {'L1': '01'}, 'L1': {'L2': '12', 'L4': '14'}, 'L2': {'L3': '23'}, 'L3': {'L1': '31'}, 'L4': {'L5': '45'}}
def get_all_paths(links, length, start=0):
paths = [[start]]
for i in range(length):
newpaths = []
for path in paths:
try:
for next_node in links[path[-1]]:
newpaths.append(path + [next_node])
except KeyError:
pass
paths = newpaths
return paths
get_all_paths(links, 3, start='L0')
#>>> [['L0', 'L1', 'L4', 'L5'], ['L0', 'L1', 'L2', 'L3']]
然后,您可以将每个路径转换为['01', '14', '45']
表单。
由于您似乎想知道如何进行最后一次转换,所以这是一个方法:
paths = [['L0', 'L1', 'L4', 'L5'], ['L0', 'L1', 'L2', 'L3']]
def join_paths(paths, links):
for path in paths:
yield [links[a][b] for a, b in zip(path, path[1:])]
list(join_paths(paths, links))
#>>> [['01', '14', '45'], ['01', '12', '23']]
zip(path, path[1:])
会将[1, 2, 3, 4]
变为[(1, 2), (2, 3), (3, 4)]
。
for a, b in
会占用每一对,并将a
和b
设置为其中的项目。
然后links[a][b]
将从字典中查找路径名称。
yield
一次一个地返回每个项目,因此您必须在list
的输出上调用join_paths
才能将其放入列表中。