如何将迭代 DFS 变成递归 DFS?
How to turn a iterative DFS into a recursive DFS?
我通过实现堆栈编写了一个迭代 DFS。现在我正在尝试递归地编写相同的 DFS,我 运行 遇到了问题。
我的问题是,当我迭代编写它时,我可以保留某些全局变量,例如paths=[]
,我会在找到新路径时添加进去。
我对递归方法感到困惑的是,基本上我想跟踪两组结果:
1) 递归访问节点寻找新路径
2) 每次找到新路径时,我都想将其添加到路径列表中,然后返回该列表。
所以我的递归函数现在被编写成 returns 基本情况下的单个路径,并且 returns 函数末尾的路径列表。
什么是更好的写法?
可运行 Python 脚本在这里:
代码在这里:
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']], []]]
要获得平面列表的结果,您要使用 list.extend()
而不是 list.append()
。
尝试这样的事情:
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')
哪个returns:
set([('A', 'C', 'F'), ('A', 'B', 'E', 'F')])
我通过实现堆栈编写了一个迭代 DFS。现在我正在尝试递归地编写相同的 DFS,我 运行 遇到了问题。
我的问题是,当我迭代编写它时,我可以保留某些全局变量,例如paths=[]
,我会在找到新路径时添加进去。
我对递归方法感到困惑的是,基本上我想跟踪两组结果:
1) 递归访问节点寻找新路径 2) 每次找到新路径时,我都想将其添加到路径列表中,然后返回该列表。
所以我的递归函数现在被编写成 returns 基本情况下的单个路径,并且 returns 函数末尾的路径列表。
什么是更好的写法?
可运行 Python 脚本在这里:
代码在这里:
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']], []]]
要获得平面列表的结果,您要使用 list.extend()
而不是 list.append()
。
尝试这样的事情:
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')
哪个returns:
set([('A', 'C', 'F'), ('A', 'B', 'E', 'F')])