BFS 基于队列实现,DFS 基于栈实现,是最基本的图算法,但是它们的扩展有很多实际用处。下面给出这两种图搜索的实现:
def bfs(graph, v):
queue = [v]
visited = set()
visited.add(v)
res = []
while queue != []:
temp = queue.pop(0)
res.append(temp)
for neighbor in graph[temp]:
if neighbor not in visited:
queue.append(neighbor)
visited.add(neighbor)
return res
def dfs(graph, v):
stack = [v]
visited = set()
visited.add(v)
res = []
while stack != []:
temp = stack.pop()
res.append(temp)
for neighbor in graph[temp]:
if neighbor not in visited:
stack.append(neighbor)
visited.add(neighbor)
return res
if __name__ == '__main__':
g = {'A': ['B', 'C'],
'B': ['A', 'C', 'D'],
'C': ['A', 'D', 'E'],
'D': ['B', 'C', 'E', 'F'],
'E': ['C', 'D'],
'F': ['D']}
print(bfs(g, 'F'))
print(dfs(g, 'F'))
这里使用了 Python 的 set 容器记录已经访问过的顶点。下面简单扩展一下 BFS,实现一个寻找无权图中任意两点最短路径的算法:
def shortestPath(graph, v, target):
queue = [v]
visited = set()
visited.add(v)
res = {}
while queue != []:
parent = queue.pop(0)
for neighbor in graph[parent]:
if neighbor not in visited:
queue.append(neighbor)
visited.add(neighbor)
res[neighbor] = parent
key = target
path = [target]
while key is not v:
path.append(res[key])
key = res[key]
return path[::-1]
if __name__ == '__main__':
g = {'A': ['B', 'C'],
'B': ['A', 'C', 'D'],
'C': ['A', 'D', 'E'],
'D': ['B', 'C', 'E', 'F'],
'E': ['C', 'D'],
'F': ['D']}
print(shortestPath(g, 'F', 'C'))
对于一个无权图来说,实际上从一点 BFS 到其他点的搜索路径就是这两点间的最短路径,只要使用一个映射(这里是一个字典)记录过程中每个顶点的 parent,最后逆向打印出来就可以了。