# 广度优先搜索
比较次数: 0
已访问节点:
# 算法原理
广度优先搜索(Breadth-First Search,简称BFS)是一种用于遍历或搜索树或图的算法。它的基本思想是从一个顶点开始,先访问该顶点的所有相邻顶点,然后再按照访问的顺序依次访问这些相邻顶点的相邻顶点,直到访问完所有可达的顶点。
# 算法步骤
- 从起始顶点开始,将其加入队列并标记为已访问
- 当队列不为空时,重复以下步骤:
- 从队列中取出一个顶点
- 访问该顶点的所有未访问的相邻顶点
- 将这些相邻顶点加入队列并标记为已访问
- 当队列为空时,算法结束
# 代码实现
// 使用队列实现BFS(邻接表表示)
function bfs(graph, start) {
const visited = new Set();
const queue = [start];
visited.add(start);
while (queue.length > 0) {
const vertex = queue.shift();
console.log(vertex); // 访问顶点
// 访问所有未访问的相邻顶点
for (const neighbor of graph[vertex]) {
if (!visited.has(neighbor)) {
visited.add(neighbor);
queue.push(neighbor);
}
}
}
}
// 在二叉树中使用BFS进行层次遍历
class TreeNode {
constructor(val) {
this.val = val;
this.left = null;
this.right = null;
}
}
function levelOrderTraversal(root) {
if (root === null) return [];
const result = [];
const queue = [root];
while (queue.length > 0) {
const levelSize = queue.length;
const currentLevel = [];
// 处理当前层的所有节点
for (let i = 0; i < levelSize; i++) {
const node = queue.shift();
currentLevel.push(node.val);
// 将下一层的节点加入队列
if (node.left) queue.push(node.left);
if (node.right) queue.push(node.right);
}
result.push(currentLevel);
}
return result;
}
# 复杂度分析
# 时间复杂度
- O(V + E),其中V是顶点数,E是边数
- 对于树形结构:O(n),其中n是节点数
# 空间复杂度
- O(V),需要visited集合和队列来存储顶点
- 在最坏情况下,队列可能需要存储所有顶点
# 算法特点
# 优点
- 可以找到最短路径
- 适合搜索最近的节点
- 不会陷入深层递归
- 按层次访问节点
# 缺点
- 空间复杂度较高
- 不适合搜索深层次的节点
- 对于图的搜索,可能需要大量内存
# 适用场景
- 寻找最短路径
- 层次遍历
- 网络爬虫
- 社交网络中的好友推荐
- 地图导航
# 实际应用
- 迷宫最短路径查找
- 网页爬虫的URL遍历
- 社交网络的好友关系分析
- GPS导航系统的路径规划
# 优化方案
- 双向BFS:从起点和终点同时开始搜索
- 启发式搜索:结合启发函数进行优化
- 多源BFS:从多个起点同时开始搜索
// 双向BFS示例(查找最短路径)
function bidirectionalBFS(graph, start, target) {
if (start === target) return 0;
const visitedFromStart = new Map([[start, 0]]);
const visitedFromTarget = new Map([[target, 0]]);
let queueFromStart = [start];
let queueFromTarget = [target];
while (queueFromStart.length > 0 && queueFromTarget.length > 0) {
// 从起点扩展
const vertex = queueFromStart.shift();
const distance = visitedFromStart.get(vertex);
for (const neighbor of graph[vertex]) {
if (visitedFromTarget.has(neighbor)) {
// 找到相交点,返回最短路径长度
return distance + visitedFromTarget.get(neighbor);
}
if (!visitedFromStart.has(neighbor)) {
visitedFromStart.set(neighbor, distance + 1);
queueFromStart.push(neighbor);
}
}
// 从终点扩展
const vertexFromTarget = queueFromTarget.shift();
const distanceFromTarget = visitedFromTarget.get(vertexFromTarget);
for (const neighbor of graph[vertexFromTarget]) {
if (visitedFromStart.has(neighbor)) {
// 找到相交点,返回最短路径长度
return distanceFromTarget + visitedFromStart.get(neighbor);
}
if (!visitedFromTarget.has(neighbor)) {
visitedFromTarget.set(neighbor, distanceFromTarget + 1);
queueFromTarget.push(neighbor);
}
}
}
return -1; // 无法到达目标顶点
}
// 多源BFS示例(计算到多个源点的最短距离)
function multiSourceBFS(graph, sources) {
const visited = new Map();
const queue = [];
// 初始化所有源点
for (const source of sources) {
visited.set(source, 0);
queue.push(source);
}
while (queue.length > 0) {
const vertex = queue.shift();
const distance = visited.get(vertex);
for (const neighbor of graph[vertex]) {
if (!visited.has(neighbor)) {
visited.set(neighbor, distance + 1);
queue.push(neighbor);
}
}
}
return visited;
}