📅  最后修改于: 2023-12-03 15:09:47.326000             🧑  作者: Mango
广度优先遍历(BFS)是一种图形搜索算法,它从一个节点(起点)开始,先访问它的所有邻居节点,再访问邻居节点的邻居节点,直到所有节点都被访问。
广度优先遍历可以用来解决很多问题,例如查找最短路径、寻找连通块、拓扑排序等。
在一个无向图或有向图中,可以使用广度优先遍历来查找两个节点之间的最短路径。
下面是一个示例代码,展示了如何使用BFS来找到起点到终点的最短路径。其中的 Graph
类表示一个无向图。
from collections import deque
class Graph:
def __init__(self):
self.adj = {}
def add_edge(self, u, v):
if u not in self.adj:
self.adj[u] = []
if v not in self.adj:
self.adj[v] = []
self.adj[u].append(v)
self.adj[v].append(u)
def bfs(self, source, target):
visited = {source}
queue = deque([(source, [source])])
while queue:
node, path = queue.popleft()
if node == target:
return path
for neighbor in self.adj[node]:
if neighbor not in visited:
visited.add(neighbor)
queue.append((neighbor, path + [neighbor]))
return None
**代码解释**
- `visited`: 已访问的节点的集合,用于避免重复访问。
- `queue`: 存储节点和节点的路径的队列。
- `node`: 当前节点。
- `path`: 当前节点到起点的路径。
代码首先将起点添加到已访问节点集合中,并将其加入队列中。然后,它将从队头中取出一个节点,并找到与其相邻的未访问节点。对于每个未访问节点,代码将其添加到已访问节点集合中,并将其加入队列中。同时,它会更新当前节点到该节点的路径。当找到目标节点时,代码将直接返回此时的最短路径。
## 2. 寻找连通块
在一个无向图中,可以使用广度优先遍历来找到所有可能的连通块(也称为连通分量)。下面是一个简单的示例代码。
```python
def connected_components(graph):
visited = set()
components = []
for node in graph:
if node not in visited:
component = []
queue = deque([node])
visited.add(node)
while queue:
node = queue.popleft()
component.append(node)
for neighbor in graph[node]:
if neighbor not in visited:
visited.add(neighbor)
queue.append(neighbor)
components.append(component)
return components
代码首先创建一个空的已访问节点集合和一个空的连通块集合。然后,对于图中的每个节点,它检查它是否已被访问,如果没有,则开始一个新的连通块。它使用一个队列来存储节点,并将其邻居节点添加到队列中。同样地,当找到所有可达节点时,它将其添加到当前连通块中。
在有向无环图(DAG)中,可以使用广度优先遍历来进行拓扑排序,以确定节点之间的依赖关系。
下面是一个示例代码,用于对DAG进行拓扑排序:
from collections import defaultdict, deque
def topo_sort(graph):
indegrees = defaultdict(int)
for node in graph:
for neighbor in graph[node]:
indegrees[neighbor] += 1
queue = deque([node for node in graph if indegrees[node] == 0])
ordering = []
while queue:
node = queue.popleft()
ordering.append(node)
for neighbor in graph[node]:
indegrees[neighbor] -= 1
if indegrees[neighbor] == 0:
queue.append(neighbor)
return ordering
代码首先创建一个字典来存储每个节点的入度。然后,它使用广度优先遍历,将入度为0的节点添加到队列中,直到找到了所有节点。 对于每个节点,代码更新邻居节点的入度。如果邻居节点的入度为0,则将其添加到队列中,重复此过程直到找到所有节点。
广度优先遍历是解决图形问题的有用工具之一。它可以用于查找最短路径、寻找连通块、拓扑排序等。 在实际问题中,您可能需要根据应用程序的需要对BFS进行修改和扩展。