使用迭代方法从Python中的开始节点到达图形中的目标节点
我有下面的无向图,在图中,我试图通过所有可用路径,而不仅仅是单个或最短路径,从节点使用迭代方法从Python中的开始节点到达图形中的目标节点,python,graph,Python,Graph,我有下面的无向图,在图中,我试图通过所有可用路径,而不仅仅是单个或最短路径,从节点0开始到达节点5目标节点 图表本身就是一个字典: graph = { "0" : ["2", "1"], "2" : ["0", "3", "4"], "3" : ["2"],
0
开始到达节点5
目标节点
图表本身就是一个字典:
graph = { "0" : ["2", "1"],
"2" : ["0", "3", "4"],
"3" : ["2"],
"1" : ["0", "5"],
"4" : ["2", "5"],
"5" : ["1", "4"]
}
我的方法是从开始节点开始,然后遍历每个邻居,然后遍历它们的邻居,直到到达目的地
然而,我面临的问题是,我无法将for循环中的主要迭代更改为新的实时迭代(不可能,也不推荐)
例如,如果我开始在
0
的邻域中循环,它们是2
和1
,我会在[2,1]
中循环,然后我会在3
和4
之间循环,因为它们是2
的邻域,我不能在for循环中改变这一点,因为迭代仍将保持[2,1]
,而不是变成[3,4]
。此外,[2,1]
需要保持引用,在遍历节点3
和节点4
及其邻居[5]
之后,第一个迭代器1
中的第二个节点应该与其邻居[1]一起遍历
在这种情况下。我不确定这是否回答了您关于如何迭代执行的问题,但我建议您使用递归方法解决它,因此不同的节点可以迭代运行,而不会干扰其他节点,并且可以无限扩展。
我的意思是,您将获取相邻节点的循环,并使其成为一个函数,该函数接收目标节点和当前节点,并执行您已经实现的逻辑,对于每个不是目标节点的节点,您将在该节点上运行该函数。GL您可以使用堆栈结构以迭代方式执行此操作,该堆栈结构包含要探索的下一个节点的列表以及到达这些节点的路径 例如:
def findPath(graph, origin,target):
stack = [(origin,[origin])] # Start from origin
seen = {origin} # Track where you've been so far
while stack:
node, path = stack.pop(0) # BFS (use pop(-1) for DFS)
for nextNode in graph[node]: # Go through neighbours
if nextNode in seen: continue # not seen yet
nextPath = path + [nextNode] # Record path to get there
if nextNode == target: return nextPath # Arrived!
seen.add(nextNode) # Avoid returning here
stack.append( (nextNode,nextPath) ) # Stack for more exploration
return [] # no path to target
输出:
graph = { "0" : ["2", "1"],
"2" : ["0", "3", "4"],
"3" : ["2"],
"1" : ["0", "5"],
"4" : ["2", "5"],
"5" : ["1", "4"]
}
print(findPath(graph,"0","5"))
['0', '1', '5']
print(findPath(graph,"3","5"))
['3', '2', '4', '5']
print(findPath(graph,"1","3"))
['1', '0', '2', '3']
BFS(广度优先搜索)将查找最短路径。DFS(深度优先搜索)将消耗更少的内存,但可能无法找到最佳路径
要获得所有可能的路径,可以将此函数转换为生成器,但不能使用“SEED”优化,因为它会短路多条到达同一节点的部分路径。在这种情况下,您应该使用DFS,因为您无论如何都要探索所有路径,并且DFS将更高效地使用内存
def findPaths(graph, origin,target):
stack = [(origin,[origin])] # Start from origin
while stack:
node, path = stack.pop(-1) # DFS (use pop(0) for BFS)
for nextNode in graph[node]: # Go through neighbours
if nextNode in path: continue # don't loop inside paths
nextPath = path + [nextNode] # Record path to get there
if nextNode == target:
yield nextPath # Return this path,
continue # continue with others
stack.append( (nextNode,nextPath) ) # Stack for more exploration
输出:
graph = { "0" : ["2", "1"],
"2" : ["0", "3", "4"],
"3" : ["2"],
"1" : ["0", "5"],
"4" : ["2", "5"],
"5" : ["1", "4"]
}
for path in findPaths(graph,"0","5"): print(path)
['0', '1', '5']
['0', '2', '4', '5']
for path in findPaths(graph,"3","5"): print(path)
['3', '2', '4', '5']
['3', '2', '0', '1', '5']
for path in findPaths(graph,"1","3"): print(path)
['1', '0', '2', '3']
['1', '5', '4', '2', '3']
多亏了Alain T,这个图在哪里呢?我假设这个图是由节点对象组成的,这些节点对象有一个“邻居”属性,包含一个连接节点的列表。你没有提供任何样本数据或数据结构,所以我不得不编一个。你是对的。这是可以做到的。不过,我编辑这个问题是为了解决你说的问题,让它更清楚。谢谢阿兰的及时编辑。我认为我犯了一个错误,没有在问题中提到,我正在寻找到图形的所有路径,因此这就是问题发生的地方。我再次编辑我的问题。我还添加了问题中出现的图中节点2和3之间的边。