Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 查找树中两个节点之间的(保证唯一)路径_Python_Networkx_Graph Traversal - Fatal编程技术网

Python 查找树中两个节点之间的(保证唯一)路径

Python 查找树中两个节点之间的(保证唯一)路径,python,networkx,graph-traversal,Python,Networkx,Graph Traversal,我有一个(可能)简单的图遍历问题。我是一个图形新手,使用networkx作为我的图形数据结构。我的图表总是这样: 0 1 8 2 3 9 10 4 5 6 7 11 12 13 14 我需要返回从根节点到给定节点的路径(例如,path(0,11)应该返回[0,8,9,11]) 我有一个解决方案,它通过传递一个不断增长和收缩的列表来跟踪遍历树时路径的外观,最终在找到目标节点时返回

我有一个(可能)简单的图遍历问题。我是一个图形新手,使用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()

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

失败时返回
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
我不知道您正在使用的图形库,但我假设即使leaf也包含一个
neights\u iter
方法,这显然不应该为leaf生成任何子对象。在这种情况下,可以省去叶的显式检查,使其略短一些:

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
的真实部分中,您是从函数返回的。这是很常见的(有些老同学不喜欢)。这将删除一些不必要的缩进。

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

但是你的问题也是关于在深度优先搜索实现中使用堆栈而不是列表,对吗?你在这里得到了一种味道:

简而言之,你

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

###=
对于start.com中的v:
如果depthFirstSearch(v,isGoal,result):
返回真值

直接使用networkx:


所有简单路径(G,source,target,cutoff=None)

在python中实现图形的必读答案可能在这里:@GL770使用
inspect
模块直接查找堆栈,这样一个简单的图形算法对我来说似乎不是很优雅。@GL770-这是一个不错的主意,但不是非常优雅。一般来说,我希望堆栈内容通过一系列“return”语句而不是直接检查出来。这正是我所希望的。谢谢你的帮助。。。我曾经考虑过这个想法,但它并没有为我实现。(顺便说一句,我对它进行了测试,它按照描述工作,尽管您在第5行有一个尾随“:”需要删除)感谢您的回复。这是对公认答案的一个很好的解释(两者基本上是等价的)。多角度总是好的+1您能提供一个带有硬编码图和测试用例的示例代码吗?
###<<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