如何将迭代DFS转换为递归DFS?

时间:2015-06-12 22:50:52

标签: python recursion depth-first-search

我通过实现堆栈编写了迭代DFS。现在我试图递归地编写相同的DFS,我遇到了问题。

我的问题是,当我迭代地编写它时,我可以保留某些全局变量,例如paths=[],当我找到新路径时,我会添加它。

我对递归方法感到困惑的是,基本上有两组结果我想跟踪:

1)递归访问节点以查找新路径 2)每次找到新路径时,我都希望将其添加到路径列表中,然后返回。

所以现在编写我的递归函数,使它在基本情况下返回单个路径,并返回函数末尾的路径列表。

有什么更好的方式来写这个?

这里可运行的Python脚本:

https://ideone.com/ekfFDP

代码在这里:

graph = {'A': ['B', 'C'],
         'B': ['A', 'D', 'E'],
         'C': ['A', 'F'],
         'D': ['B'],
         'E': ['B', 'F'],
         'F': ['C', 'E'],
         'G': ['K']}


def push(array, item):
    array.insert(0, item)

def pop(array):
    return array.pop(0)

def dfs_paths(graph, start, goal):
    paths = []
    stack = [(start, [start])]

    while stack:
        (vertex, path) = pop(stack)
        vertices = graph[vertex]

        for next_vertex in (set(vertices) - set(path)):
            new_path = path + [next_vertex]

            if next_vertex == goal:
                paths.append(new_path)
            else:
                push(stack, (next_vertex, new_path))

    return paths

print dfs_paths(graph, 'A', 'F') # [['A', 'C', 'F'], ['A', 'B', 'E', 'F']]

def dfs_paths_rec(graph, start, goal, path=[]):
    if start == goal:
        path.append(start)
        return path

    paths = []
    for next in set(graph[start]) - set(path):
        new_path = dfs_paths_rec(graph, next, goal, path + [next])
        paths.append(new_path)

    return paths

print dfs_paths_rec(graph, 'A', 'F')

# [[[[[['C', 'A', 'B', 'E', 'F', 'F']], []]], ['C', 'F', 'F']], [[[['B', 'A', 'C', 'F', 'F']]], [['B', 'E', 'F', 'F']], []]]

2 个答案:

答案 0 :(得分:1)

要以平面列表形式获取结果,您希望使用list.extend()代替/*---------------------------------- OVERLAYS ----------------------------------*/ .overlay { background: rgba(34, 34, 34, 0.73); position: relative; width: 300px; height: 300px; border: 1px solid red; opacity: 0; &:hover { opacity: 1; } } .storefront { position: relative; }

答案 1 :(得分:0)

尝试这样的事情:

def all_paths_dfs(graph, start, end, path=None):
    if path is None:
        path = []

    path.append(start)
    all_paths = set()

    if start == end:
        all_paths.add(tuple(path))
    else:
        for neighbor in graph[start]:
            if neighbor not in path:
                all_paths |= all_paths_dfs(graph, neighbor, end, path)

    path.pop()
    return all_paths


if __name__ == "__main__":
    graph = {'A': {'B', 'C'},
             'B': {'A', 'D', 'E'},
             'C': {'A', 'F'},
             'D': {'B'},
             'E': {'B', 'F'},
             'F': {'C', 'E'},
             'G': {'K'}}

    print all_paths_dfs(graph, 'A', 'F')

返回:

set([('A', 'C', 'F'), ('A', 'B', 'E', 'F')])