元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
算法基础
▶
复杂度分析
时间复杂度
空间复杂度
渐进符号
▶
算法思想
分治法
贪心算法
回溯法
概率算法
枚举算法
递推算法
递归算法
动态规划
分支限界法
模拟算法
▶
算法分析
正确性证明
性能优化
算法比较
▶
搜索算法
▶
基本搜索
顺序搜索
二分搜索
插值搜索
▶
图搜索
深度优先搜索
广度优先搜索
启发式搜索
▶
高级搜索
双向搜索
A*算法
模式匹配
▶
排序算法
▶
比较类排序
冒泡排序
快速排序
归并排序
插入排序
选择排序
▶
非比较类排序
计数排序
基数排序
桶排序
▶
高级排序
堆排序
希尔排序
外部排序
拓扑排序
▶
图论算法
▶
图的表示
邻接矩阵
邻接表
边集数组
▶
最短路径
Dijkstra算法
Floyd算法
Bellman-Ford算法
最短路径概述
▶
生成树
Prim算法
Kruskal算法
并查集
最小生成树
▶
图的连通性
强连通分量
割点与桥
双连通分量
欧拉路径
▶
动态规划
▶
基础概念
最优子结构
重叠子问题
状态转移方程
▶
经典问题
背包问题
最长公共子序列
编辑距离
▶
优化技巧
空间优化
状态压缩
区间动态规划
▶
字符串算法
▶
字符串匹配
KMP算法
Boyer-Moore算法
Sunday算法
▶
字符串处理
字典树
后缀数组
字符串哈希
▶
压缩算法
游程编码
Huffman编码
LZ77算法
发布时间:
2025-03-21 18:27
↑
☰
# 广度优先搜索 广度优先搜索(Breadth-First Search,简称BFS)是一种用于遍历或搜索树或图的算法。该算法从根节点开始,首先访问所有相邻节点,然后再访问下一层节点,按层次逐步扩展,直到找到目标或遍历完整个图。 ## 基本原理 广度优先搜索的工作原理如下: 1. 从起始节点开始 2. 将起始节点加入队列 3. 访问队列中的第一个节点,并将其所有未访问的相邻节点加入队列 4. 重复步骤3,直到队列为空或找到目标节点 ## 代码实现 ### 基本实现(图) ```python from collections import deque class Graph: def __init__(self): self.graph = {} # 邻接表表示 def add_edge(self, u, v): if u not in self.graph: self.graph[u] = [] self.graph[u].append(v) def bfs(self, start): visited = set() queue = deque([start]) visited.add(start) while queue: vertex = queue.popleft() print(vertex, end=' ') # 将所有未访问的相邻节点加入队列 for neighbor in self.graph.get(vertex, []): if neighbor not in visited: visited.add(neighbor) queue.append(neighbor) # 使用示例 graph = Graph() graph.add_edge(0, 1) graph.add_edge(0, 2) graph.add_edge(1, 2) graph.add_edge(2, 0) graph.add_edge(2, 3) graph.add_edge(3, 3) print("广度优先遍历(从节点0开始):") graph.bfs(0) ``` ### 带层次信息的实现 ```python def bfs_with_level(graph, start): visited = set([start]) queue = deque([(start, 0)]) # (节点, 层次) levels = {start: 0} while queue: vertex, level = queue.popleft() print(f"Level {level}: {vertex}") for neighbor in graph.get(vertex, []): if neighbor not in visited: visited.add(neighbor) queue.append((neighbor, level + 1)) levels[neighbor] = level + 1 return levels # 使用示例 graph = { 0: [1, 2], 1: [2], 2: [0, 3], 3: [3] } levels = bfs_with_level(graph, 0) print("每个节点的层次:", levels) ``` ## 性能分析 ### 时间复杂度 - 邻接表表示:O(V + E),其中V是顶点数,E是边数 - 邻接矩阵表示:O(V²) ### 空间复杂度 - O(V),用于存储访问状态和队列 ### 优缺点分析 优点: 1. 保证找到最短路径 2. 适合寻找最近的节点 3. 按层次访问,便于分析层次关系 4. 不会陷入深度递归 缺点: 1. 内存占用较大 2. 不适合搜索深层节点 3. 对于稀疏图效率较低 ## 应用场景 1. 最短路径问题 2. 社交网络分析 3. 网页爬虫 4. 地图导航 ## 实际应用示例 ### 1. 最短路径查找 ```python def find_shortest_path(graph, start, end): if start == end: return [start] visited = {start} queue = deque([(start, [start])]) while queue: vertex, path = queue.popleft() for neighbor in graph.get(vertex, []): if neighbor == end: return path + [neighbor] if neighbor not in visited: visited.add(neighbor) queue.append((neighbor, path + [neighbor])) return None # 没有找到路径 # 使用示例 graph = { 'A': ['B', 'C'], 'B': ['A', 'D', 'E'], 'C': ['A', 'F'], 'D': ['B'], 'E': ['B', 'F'], 'F': ['C', 'E'] } path = find_shortest_path(graph, 'A', 'F') print("最短路径:", ' -> '.join(path) if path else "没有找到路径") ``` ### 2. 单词阶梯问题 ```python def word_ladder(start, end, dictionary): if end not in dictionary: return None dictionary = set(dictionary) queue = deque([(start, [start])]) visited = {start} while queue: word, path = queue.popleft() # 尝试改变单词的每个字母 for i in range(len(word)): for c in 'abcdefghijklmnopqrstuvwxyz': new_word = word[:i] + c + word[i+1:] if new_word == end: return path + [new_word] if new_word in dictionary and new_word not in visited: visited.add(new_word) queue.append((new_word, path + [new_word])) return None # 使用示例 dictionary = {'hot', 'dot', 'dog', 'lot', 'log', 'cog'} start = 'hit' end = 'cog' path = word_ladder(start, end, dictionary) print("单词阶梯:", ' -> '.join(path) if path else "没有找到路径") ``` ## 优化技巧 1. 双向BFS ```python def bidirectional_bfs(graph, start, end): if start == end: return [start] # 从起点和终点同时开始搜索 forward_queue = deque([(start, [start])]) backward_queue = deque([(end, [end])]) forward_visited = {start: [start]} backward_visited = {end: [end]} while forward_queue and backward_queue: # 从起点扩展 vertex, path = forward_queue.popleft() for neighbor in graph.get(vertex, []): if neighbor in backward_visited: # 找到交点,合并路径 return path + backward_visited[neighbor][::-1][1:] if neighbor not in forward_visited: forward_visited[neighbor] = path + [neighbor] forward_queue.append((neighbor, path + [neighbor])) # 从终点扩展 vertex, path = backward_queue.popleft() for neighbor in graph.get(vertex, []): if neighbor in forward_visited: # 找到交点,合并路径 return forward_visited[neighbor] + path[::-1][1:] if neighbor not in backward_visited: backward_visited[neighbor] = path + [neighbor] backward_queue.append((neighbor, path + [neighbor])) return None ``` 2. 优先队列BFS ```python from heapq import heappush, heappop def priority_bfs(graph, start, heuristic): visited = set() pq = [(heuristic(start), start)] while pq: _, vertex = heappop(pq) if vertex not in visited: visited.add(vertex) print(vertex, end=' ') for neighbor in graph.get(vertex, []): if neighbor not in visited: heappush(pq, (heuristic(neighbor), neighbor)) ``` ## 常见问题和解决方案 1. 内存占用过大 - 使用迭代器而不是列表存储邻居节点 - 及时释放不需要的数据 - 考虑使用位图标记访问状态 2. 处理无向图 ```python def add_undirected_edge(graph, u, v): if u not in graph: graph[u] = [] if v not in graph: graph[v] = [] graph[u].append(v) graph[v].append(u) ``` 3. 检测环 ```python def has_cycle_bfs(graph, start): parent = {start: None} queue = deque([start]) while queue: vertex = queue.popleft() for neighbor in graph.get(vertex, []): if neighbor in parent: if neighbor != parent[vertex]: return True else: parent[neighbor] = vertex queue.append(neighbor) return False ``` ## 总结 广度优先搜索是一种重要的图遍历算法,它通过队列实现按层次访问节点的功能。BFS的主要特点是能够找到最短路径,适合在需要寻找最近节点或按层次分析的场景中使用。在实际应用中,我们可以根据具体需求选择合适的实现方式,并使用适当的优化技巧来提高算法的效率。同时,要注意处理好内存占用、无向图和环检测等常见问题,确保算法的正确性和稳定性。