已发布·持续改进
Algorithm
图遍历用 BFS 或 DFS 访问所有可达顶点,是无权最短路径、连通分量、环检测和拓扑排序的基础。
图遍历是指在由顶点和边组成的图中,从起点出发沿着边访问所有可达顶点,并且每个顶点只访问一次。最基本的两种方法是广度优先搜索(BFS)和深度优先搜索(DFS):BFS 用队列从近到远逐层扩展,DFS 用栈或递归沿一条路径走到尽头再回溯。图通常用邻接表或邻接矩阵存储,迷宫这类二维网格只要把每个格子看作顶点,也可以用同样的方法处理。
道路网络、社交关系、任务依赖和网页链接都是图。BFS 能在所有边代价相同的图中求最短路径,DFS 则是连通分量、环检测和拓扑排序的骨架。构建工具安排任务顺序、垃圾回收器判断对象是否可达、图像编辑器的油漆桶填充都依赖图遍历,它也是技术面试和算法题中最常见的题型之一。
建议先在纸上画一个小图,手动跟踪 BFS 的队列和 DFS 的调用栈如何变化。然后自己实现这两种算法,重点注意何时标记已访问、如何记录距离和父节点。接着再练习网格最短路径、统计连通分量以及用 Kahn 算法做拓扑排序。
邻接表占用 O(V + E) 内存,适合稀疏图;邻接矩阵能在 O(1) 内判断边是否存在,但需要 O(V^2) 内存。
用队列先访问距离近的顶点,因此在无权图中第一次得到的距离就是最短距离。
用递归或栈一路深入再回溯,是连通分量、环检测和回溯法的基础。
在有向无环图中,用 Kahn 算法或 DFS 完成顺序的逆序,得到满足所有依赖关系的顺序。
程序用字典形式的邻接表构建一个 6 个顶点的无向图,然后用基于 deque 的 BFS 输出从 A 到各顶点的最少边数,用递归 DFS 输出访问顺序。两个函数都会记录已访问的顶点,不会重复处理同一个顶点。
graph_traversal.py
from collections import deque
graph = {
"A": ["B", "C"],
"B": ["A", "D"],
"C": ["A", "D", "E"],
"D": ["B", "C", "F"],
"E": ["C", "F"],
"F": ["D", "E"],
}
def bfs(start):
"""Shortest number of edges from start to every reachable vertex."""
dist = {start: 0}
queue = deque([start])
while queue:
node = queue.popleft()
for nxt in graph[node]:
if nxt not in dist:
dist[nxt] = dist[node] + 1
queue.append(nxt)
return dist
def dfs(start):
"""Vertices in depth-first visiting order."""
order, seen = [], set()
def visit(node):
seen.add(node)
order.append(node)
for nxt in graph[node]:
if nxt not in seen:
visit(nxt)
visit(start)
return order
print(bfs("A")) # {'A': 0, 'B': 1, 'C': 1, 'D': 2, 'E': 2, 'F': 3}
print(dfs("A")) # ['A', 'B', 'D', 'C', 'E', 'F']
python graph_traversal.py共六章,带你从安装一步步了解 图遍历 的核心概念。
在这里提问、分享经验,交流关于 图遍历 的看法。
还没有讨论。来发起第一个吧。
0 条评论
登录 · 登录后即可发表评论。
来发表第一条评论吧。