在python中深度优先搜索算法

时间:2015-10-12 05:35:30

标签: python python-2.7 python-3.x depth-first-search

(此问题在此处进行了详细介绍:python-search-algorithm-from-implied-graphs

假设我有一个接受输入($ x_i $)的函数,然后经历一个循环并产生一系列输出($ x_ {i,j} $)。然后每个输出可以再次输入到同一函数,产生更多输出($ x_ {i,j,k} $)。我试图通过此功能找到一组特定结束状态的步骤。

这是一个普遍的问题,我的问题是python中有什么好的代码结构来处理这个问题。

这里以一些元代码为例(尽管在实践中可能会更复杂):

def f(x):
  for i in range(n):
    if some_condition:
      yield g(x,i) 
  yield false

然后对于一些$ x_0 $和一些$ y $,我们正在寻找序列$ x_0,x_1,\ ldots,x_k $,这样$ x_k = y $和$ x_ {j + 1 } = g(x_j,i_j)$ for $ j \ in {0,\ ldots,k-1} $。

要使用深度优先搜索执行此操作,您将首先计算$ f(f(\ ldots f(x)\ ldots))$,直到它产生目标结果或为false。然后备份一步并从$ f $产生第二个结果并重复(粗略描述,但你得到的想法:基本上是深度优先搜索)。

在我看来,yield关键字处理这个问题效率很低。您还必须以允许您返回的方式处理$(x,f(x),f(f(x)),\ ldots)$的堆栈(我认为这是正确的术语)当你走到死路时追踪。

这个一般性的问题是我偶尔遇到的问题,我有点解决它 ad hoc ,但我想知道是否有一个很好的通用结构来解决这个问题,自然而有效地处理堆栈并在python中探索可能解决方案的树。

我希望这个问题足够明确。我欢迎任何想法,评论,澄清或答案。

2 个答案:

答案 0 :(得分:2)

class Tree:
def __init__(self, value, children = None):
    self.value = value
    self.children = []
    if children:
        self.children = list(children)

def get_children(self):
    return list(self.children)

def get_value(self):
    return self.value

def has_children(self):
    if self.children:
        return True

node9 = Tree(9)
node5 = Tree(5, [node9])
node6 = Tree(6)
node3 = Tree(3, [node5, node6])
node7 = Tree(7)
node8 = Tree(8)
node4 = Tree(4, [node7, node8])
node2 = Tree(2)
node1 = Tree(1, [node2, node4, node3])

def iterate_child(child):
    global level
    print ' ' * level * 2, child.get_value()
    if child.has_children():
        level += 1
        for s_child in child.get_children():
            iterate_child(s_child)
        level -= 1

level = 1
print node1.get_value()
for child in node1.get_children():
    iterate_child(child)

Printing in Depth First Order

正如您在上图中所看到的,我已遍历node1的子节点,并首先在子节点的子节点上递归迭代,然后处理父节点的第二个子节点。

答案 1 :(得分:2)

我认为只使用显式堆栈作为当前路径和递归更简单:

def search(start_state, neighbors, goal):
    path = [start_state]

    class PathFound(RuntimeError):
        pass

    def rsearch(x):
        if goal(x):
            raise PathFound
        for y in neighbors(x):
            path.append(y)
            rsearch(y)
            path.pop()

    try:
        rsearch(start_state)
    except PathFound:
        return path

    return None # No path exists

Python具有较低的递归限制,但对于深度优先搜索,这通常不是问题(并且可以通过sys.setrecursionlimit进行扩展。)