我有一个(可能)简单的图遍历问题。我是使用networkx作为我的图形数据结构的图形新手。我的图表总是如下所示:
0
1 8
2 3 9 10
4 5 6 7 11 12 13 14
我需要返回从根节点到给定节点的路径(例如,path(0, 11)
应该返回[0, 8, 9, 11]
)。
我有一个解决方案,通过传递增长和缩小的列表来跟踪在遍历树时路径的样子,最终在找到目标节点时返回:
def VisitNode(self, node, target, path):
path.append(node)
# Base case. If we found the target, then notify the stack that we're done.
if node == target:
return True
else:
# If we're at a leaf and it isn't the target, then pop the leaf off
# our path (backtrack) and notify the stack that we're still looking
if len(self.neighbors(node)) == 0:
path.pop()
return False
else:
# Sniff down the next available neighboring node
for i in self.neighbors_iter(node):
# If this next node is the target, then return the path
# we've constructed so far
if self.VisitNode(i, target, path):
return path
# If we've gotten this far without finding the target,
# then this whole branch is a dud. Backtrack
path.pop()
我觉得在我的骨头里没有必要绕过这个“路径”列表...我应该能够使用调用堆栈跟踪这些信息,但我无法弄清楚如何...有人可以告诉我如何使用堆栈递归地解决这个问题以跟踪路径吗?
答案 0 :(得分:3)
您可以通过在失败时返回None
并在成功时返回部分路径来避免绕过路径。通过这种方式,您不会从根节点到当前节点保留某种“痕迹痕迹”,但是如果找到它,则只构建从目标返回到根的路径。未经测试的代码:
def VisitNode(self, node, target):
# Base case. If we found the target, return target in a list
if node == target:
return [node]
# If we're at a leaf and it isn't the target, return None
if len(self.neighbors(node)) == 0:
return None
# recursively iterate over children
for i in self.neighbors_iter(node):
tail = self.VisitNode(i, target)
if tail: # is not None
return [node] + tail # prepend node to path back from target
return None #none of the children contains target
我不知道您正在使用的图库,但我认为即使是叶子也包含neighbours_iter
方法,显然不应该为叶子生成任何子项。在这种情况下,您可以省略对叶子的显式检查,使其更短:
def VisitNode(self, node, target):
# Base case. If we found the target, return target in a list
if node == target:
return [node]
# recursively iterate over children
for i in self.neighbors_iter(node):
tail = self.VisitNode(i, target)
if tail: # is not None
return [node] + tail # prepend node to path back from target
return None # leaf node or none of the child contains target
我还删除了一些else
语句,因为在你从函数返回的if
的真实部分内部。这是常见的refactering pattern(一些老派人士不喜欢)。这消除了一些不必要的缩进。
答案 1 :(得分:1)
您可以避免路径参数在方法体中初始化路径。如果方法在找到完整路径之前返回,则它可能返回一个空列表。
但你的问题也是关于在Depth-First-search实现中使用堆栈而不是列表,对吧?你在这里得到一个味道:http://en.literateprograms.org/Depth-first_search_%28Python%29。
简而言之,你
def depthFirstSearch(start, isGoal, result):
###ensure we're not stuck in a cycle
result.append(start)
###check if we've found the goal
###expand each child node in order, returning if we find the goal
# No path was found
result.pop()
return False
带
###<<expand each child node in order, returning if we find the goal>>=
for v in start.successors:
if depthFirstSearch(v, isGoal, result):
return True
和
###<<check if we've found the goal>>=
if isGoal(start):
return True
答案 2 :(得分:0)
直接使用networkx:
all_simple_paths(G,source,target,cutoff = None)