pygorithm/graph/iter_graph.py

73 lines
2.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

"""
广度优先遍历:
广度优先遍历是一种由近及远的遍历方式,从某个节点出发,始终优先访问距离最近的顶点,
并一层层向外扩张。
BFS 通常借助队列来实现,代码如下所示。队列具有“先入先出”的性质,
这与 BFS 的“由近及远”的思想异曲同工。
1. 将遍历起始顶点 startVet 加入队列,并开启循环
2. 在循环的每轮迭代中,弹出队首顶点并记录访问,然后将该顶点的所有邻接顶点加入到队列尾部。
3. 循环步骤 2. ,直到所有顶点被访问完毕后结束。
时间复杂度:
所有顶点都会入队并出队一次,使用 O(V) 时间;在遍历邻接顶点的过程中,由于是无向图,
因此所有边都会被访问2次使用2O(E)时间总体使用O(V+E)时间。
"""
from collections import deque
from .graph import GraphAdjList, Vertex
def graph_bfs(graph: GraphAdjList, start_vet: Vertex):
res = []
visited = set[Vertex]([start_vet])
que = deque[Vertex]([start_vet])
while len(que) > 0:
vet = que.popleft()
res.append(vet)
for adj_vet in graph.adj_list[vet]:
if adj_vet in visited:
continue
que.append(adj_vet)
visited.add(adj_vet)
return res
"""
深度优先遍历: 深度优先遍历是一种优先走到底、无路可走再回头的遍历方式。如,从左上角顶点出发,访问当前顶点的某个邻接顶点,
直到走到尽头时返回,再继续走到尽头并返回,以此类推,直至所有顶点遍历完成。
这种“走到尽头再返回”的算法范式通常基于递归来实现。
深度优先遍历的算法流程如图 9-12 所示。
直虚线代表向下递推,表示开启了一个新的递归方法来访问新顶点。
曲虚线代表向上回溯,表示此递归方法已经返回,回溯到了开启此方法的位置。
"""
def dfs(graph: GraphAdjList, visited: set[Vertex], res: list[Vertex], vet: Vertex):
"""深度优先遍历 DFS 辅助函数"""
res.append(vet) # 记录访问顶点
visited.add(vet) # 标记该顶点已被访问
# 遍历该顶点的所有邻接顶点
for adjVet in graph.adj_list[vet]:
if adjVet in visited:
continue # 跳过已被访问的顶点
# 递归访问邻接顶点
dfs(graph, visited, res, adjVet)
def graph_dfs(graph: GraphAdjList, start_vet: Vertex) -> list[Vertex]:
"""深度优先遍历 DFS"""
# 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
# 顶点遍历序列
res = []
# 哈希表,用于记录已被访问过的顶点
visited = set[Vertex]()
dfs(graph, visited, res, start_vet)
return res