3

我有一个(可能)简单的图遍历问题。我是使用 networkx 作为我的图形数据结构的图形新手。我的图表总是这样:

             0
      1              8
   2     3       9      10
 4  5   6 7    11 12  13  14

我需要返回从根节点到给定节点的路径(例如,path(0, 11)应该 return [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()

我从骨子里觉得没有必要传递这个“路径”列表......我应该能够使用调用堆栈跟踪该信息,但我不知道如何......有人可以启发我如何使用堆栈递归地解决这个问题来跟踪路径?

4

3 回答 3

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你从函数返回的真实部分中。这是常见的重构模式(一些老派的人不喜欢)。这消除了一些不必要的缩进。

于 2013-09-28T21:27:25.893 回答
1

您可以完全避免在方法主体中初始化路径的路径参数。如果方法在找到完整路径之前返回,它可能会返回一个空列表。

但是您的问题也是关于在深度优先搜索实现中使用堆栈而不是列表,对吗?您可以在这里找到一种味道: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
于 2013-09-28T22:13:04.353 回答
0

直接使用networkx:

all_simple_paths(G,源,目标,截止=无)

于 2013-10-06T11:18:38.657 回答