当前位置: 首页 > news >正文

算法精讲:广度优先搜索(BFS)——从原理到实战的完整指南

算法精讲:广度优先搜索(BFS)——从原理到实战的完整指南

深入剖析BFS算法的核心思想,提供多种Java实现方案,并通过LeetCode真题详解应用场景,帮助读者系统掌握这一基础而重要的图遍历算法。

1. 算法深度解析

1.1 什么是广度优先搜索?

广度优先搜索(Breadth-First Search,BFS)是一种系统性地遍历或搜索树或图的算法策略。它的核心思想是"由近及远、层层推进",类似于水波纹的扩散方式。
核心特征:
  • 层次性:按距离起始节点的远近顺序访问
  • 最优性:在无权图中保证找到最短路径
  • 完备性:只要解存在,一定能找到
  • 队列驱动:基于FIFO队列实现

1.2 算法思想与数学基础

BFS可以形式化描述为:
设图 G = (V, E),起始节点 s ∈ V:
  1. 初始化:所有节点颜色为白色(未访问)
  2. 将s标记为灰色(已发现但未处理),d[s] = 0
  3. 将s加入队列Q
  4. while Q ≠ ∅:
  • u = Dequeue(Q)
  • 对每个v ∈ Adj[u]:
    • 如果v为白色:颜色变灰,d[v] = d[u] + 1,Enqueue(Q, v)
  • 颜色变黑(已处理)
这种分层遍历的特性使得BFS在解决最短路径问题时具有天然优势。

2. 核心实现与优化

2.1 图的多种表示方法

import java.util.*;

// 方法1:通用图节点类
class GraphNode {
public int val;
public List<GraphNode> neighbors;
public boolean visited;

public GraphNode(int val) {
this.val = val;
this.neighbors = new ArrayList<>();
this.visited = false;
}

public void addNeighbor(GraphNode neighbor) {
this.neighbors.add(neighbor);
}

@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
GraphNode node = (GraphNode) obj;
return val == node.val;
}

@Override
public int hashCode() {
return Objects.hash(val);
}
}

// 方法2:紧凑型图表示(适合稠密图)
class CompactGraph {
private int[][] adjacencyMatrix;
private int size;

public CompactGraph(int n) {
this.size = n;
this.adjacencyMatrix = new int[n][n];
}

public void addEdge(int u, int v) {
adjacencyMatrix[u][v] = 1;
adjacencyMatrix[v][u] = 1; // 无向图
}

public List<Integer> getNeighbors(int node) {
List<Integer> neighbors = new ArrayList<>();
for (int i = 0; i < size; i++) {
if (adjacencyMatrix[node][i] == 1) {
neighbors.add(i);
}
}
return neighbors;
}
}

// 方法3:高效邻接表
class EfficientGraph {
private Map<Integer, Set<Integer>> adjList;

public EfficientGraph() {
this.adjList = new HashMap<>();
}

public void addEdge(int u, int v) {
adjList.computeIfAbsent(u, k -> new HashSet<>()).add(v);
adjList.computeIfAbsent(v, k -> new HashSet<>()).add(u);
}

public Set<Integer> getNeighbors(int node) {
return adjList.getOrDefault(node, new HashSet<>());
}
}

2.2 基础BFS实现(生产级别)

public class ProductionBFS {

/**
* 标准BFS实现 - 生产环境级别
* 时间复杂度: O(V + E), 空间复杂度: O(V)
*/
public static List<Integer> standardBFS(GraphNode start) {
List<Integer> traversalOrder = new ArrayList<>();
if (start == null) return traversalOrder;

Queue<GraphNode> queue = new LinkedList<>();
Set<GraphNode> visited = new HashSet<>();

// 初始化
queue.offer(start);
visited.add(start);

while (!queue.isEmpty()) {
GraphNode current = queue.poll();
traversalOrder.add(current.val);

// 处理所有未访问的邻居
for (GraphNode neighbor : current.neighbors) {
if (!visited.contains(neighbor)) {
visited.add(neighbor);
queue.offer(neighbor);
}
}
}

return traversalOrder;
}

/**
* 带距离计算的BFS
* 返回每个节点到起点的最短距离
*/
public static Map<GraphNode, Integer> bfsWithDistance(GraphNode start) {
Map<GraphNode, Integer> distances = new HashMap<>();
if (start == null) return distances;

Queue<GraphNode> queue = new LinkedList<>();
Set<GraphNode> visited = new HashSet<>();

queue.offer(start);
visited.add(start);
distances.put(start, 0);

while (!queue.isEmpty()) {
GraphNode current = queue.poll();
int currentDistance = distances.get(current);

for (GraphNode neighbor : current.neighbors) {
if (!visited.contains(neighbor)) {
visited.add(neighbor);
distances.put(neighbor, currentDistance + 1);
queue.offer(neighbor);
}
}
}

return distances;
}

/**
* 带路径重建的BFS
* 可以找到从起点到任意节点的最短路径
*/
public static class BFSResult {
public Map<GraphNode, Integer> distances;
public Map<GraphNode, GraphNode> predecessors;

public BFSResult() {
this.distances = new HashMap<>();
this.predecessors = new HashMap<>();
}
}

public static BFSResult bfsWithPathReconstruction(GraphNode start) {
BFSResult result = new BFSResult();
if (start == null) return result;

Queue<GraphNode> queue = new LinkedList<>();
Set<GraphNode> visited = new HashSet<>();

queue.offer(start);
visited.add(start);
result.distances.put(start, 0);
result.predecessors.put(start, null);

while (!queue.isEmpty()) {
GraphNode current = queue.poll();
int currentDistance = result.distances.get(current);

for (GraphNode neighbor : current.neighbors) {
if (!visited.contains(neighbor)) {
visited.add(neighbor);
result.distances.put(neighbor, currentDistance + 1);
result.predecessors.put(neighbor, current);
queue.offer(neighbor);
}
}
}

return result;
}

/**
* 重建从起点到目标节点的最短路径
*/
public static List<Integer> reconstructPath(GraphNode start, GraphNode target, 
Map<GraphNode, GraphNode> predecessors) {
List<Integer> path = new LinkedList<>();
if (!predecessors.containsKey(target)) return path; // 不可达

GraphNode current = target;
while (current != null) {
path.add(0, current.val);
current = predecessors.get(current);
}

// 验证路径是否真的从start开始
if (path.get(0) != start.val) {
return new ArrayList<>(); // 没有有效路径
}

return path;
}
}

2.3 层级遍历的多种变体

/**
* BFS层级遍历的高级实现
*/
public class AdvancedLevelBFS {

/**
* 标准层级遍历
*/
public static List<List<Integer>> levelOrderTraversal(GraphNode start) {
List<List<Integer>> result = new ArrayList<>();
if (start == null) return result;

Queue<GraphNode> queue = new LinkedList<>();
Set<GraphNode> visited = new HashSet<>();

queue.offer(start);
visited.add(start);

while (!queue.isEmpty()) {
int levelSize = queue.size();
List<Integer> currentLevel = new ArrayList<>();

for (int i = 0; i < levelSize; i++) {
GraphNode current = queue.poll();
currentLevel.add(current.val);

for (GraphNode neighbor : current.neighbors) {
if (!visited.contains(neighbor)) {
visited.add(neighbor);
queue.offer(neighbor);
}
}
}
result.add(currentLevel);
}

return result;
}

/**
* 之字形层级遍历
*/
public static List<List<Integer>> zigzagLevelOrder(GraphNode start) {
List<List<Integer>> result = new ArrayList<>();
if (start == null) return result;

Queue<GraphNode> queue = new LinkedList<>();
Set<GraphNode> visited = new HashSet<>();
boolean leftToRight = true;

queue.offer(start);
visited.add(start);

while (!queue.isEmpty()) {
int levelSize = queue.size();
LinkedList<Integer> currentLevel = new LinkedList<>();

for (int i = 0; i < levelSize; i++) {
GraphNode current = queue.poll();

if (leftToRight) {
currentLevel.addLast(current.val);
} else {
currentLevel.addFirst(current.val);
}

for (GraphNode neighbor : current.neighbors) {
if (!visited.contains(neighbor)) {
visited.add(neighbor);
queue.offer(neighbor);
}
}
}

result.add(new ArrayList<>(currentLevel));
leftToRight = !leftToRight;
}

return result;
}

/**
* 获取每层最右侧节点(右视图)
*/
public static List<Integer> rightSideView(GraphNode start) {
List<Integer> result = new ArrayList<>();
if (start == null) return result;

Queue<GraphNode> queue = new LinkedList<>();
Set<GraphNode> visited = new HashSet<>();

queue.offer(start);
visited.add(start);

while (!queue.isEmpty()) {
int levelSize = queue.size();

for (int i = 0; i < levelSize; i++) {
GraphNode current = queue.poll();

// 如果是当前层最后一个节点,加入结果
if (i == levelSize - 1) {
result.add(current.val);
}

for (GraphNode neighbor : current.neighbors) {
if (!visited.contains(neighbor)) {
visited.add(neighbor);
queue.offer(neighbor);
}
}
}
}

return result;
}
}

3. 高级应用与LeetCode实战

3.1 矩阵类问题

/**
* 矩阵BFS问题合集
*/
public class MatrixBFSProblems {

/**
* LeetCode 200 - 岛屿数量
* 时间复杂度: O(M×N), 空间复杂度: O(min(M,N))
*/
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0) return 0;

int rows = grid.length;
int cols = grid[0].length;
int islandCount = 0;
int[][] directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (grid[i][j] == '1') {
islandCount++;
bfsMarkIsland(grid, i, j, rows, cols, directions);
}
}
}

return islandCount;
}

private void bfsMarkIsland(char[][] grid, int row, int col, 
int rows, int cols, int[][] directions) {
Queue<int[]> queue = new LinkedList<>();
queue.offer(new int[]{row, col});
grid[row][col] = '0'; // 标记为已访问

while (!queue.isEmpty()) {
int[] current = queue.poll();
int currentRow = current[0];
int currentCol = current[1];

for (int[] dir : directions) {
int newRow = currentRow + dir[0];
int newCol = currentCol + dir[1];

if (newRow >= 0 && newRow < rows && 
newCol >= 0 && newCol < cols && 
grid[newRow][newCol] == '1') {

grid[newRow][newCol] = '0';
queue.offer(new int[]{newRow, newCol});
}
}
}
}

/**
* LeetCode 542 - 01矩阵
* 多源BFS经典问题
*/
public int[][] updateMatrix(int[][] mat) {
if (mat == null || mat.length == 0) return mat;

int rows = mat.length;
int cols = mat[0].length;
int[][] result = new int[rows][cols];
Queue<int[]> queue = new LinkedList<>();
int[][] directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

// 初始化:所有0的位置入队,1的位置标记为最大值
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (mat[i][j] == 0) {
queue.offer(new int[]{i, j});
result[i][j] = 0;
} else {
result[i][j] = Integer.MAX_VALUE;
}
}
}

// 多源BFS
while (!queue.isEmpty()) {
int[] current = queue.poll();
int row = current[0];
int col = current[1];

for (int[] dir : directions) {
int newRow = row + dir[0];
int newCol = col + dir[1];

if (newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols) {
if (result[newRow][newCol] > result[row][col] + 1) {
result[newRow][newCol] = result[row][col] + 1;
queue.offer(new int[]{newRow, newCol});
}
}
}
}

return result;
}

/**
* LeetCode 286 - 墙与门
* 填充每个房间到最近门的距离
*/
public void wallsAndGates(int[][] rooms) {
if (rooms == null || rooms.length == 0) return;

int rows = rooms.length;
int cols = rooms[0].length;
Queue<int[]> queue = new LinkedList<>();
int[][] directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

// 所有门入队
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (rooms[i][j] == 0) {
queue.offer(new int[]{i, j});
}
}
}

// BFS遍历
while (!queue.isEmpty()) {
int[] current = queue.poll();
int row = current[0];
int col = current[1];

for (int[] dir : directions) {
int newRow = row + dir[0];
int newCol = col + dir[1];

if (newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols 
&& rooms[newRow][newCol] == Integer.MAX_VALUE) {

rooms[newRow][newCol] = rooms[row][col] + 1;
queue.offer(new int[]{newRow, newCol});
}
}
}
}
}

3.2 字符串与状态搜索

/**
* 字符串BFS问题
*/
public class StringBFSProblems {

/**
* LeetCode 127 - 单词接龙
* 双向BFS优化版本
*/
public int ladderLength(String beginWord, String endWord, List<String> wordList) {
Set<String> wordSet = new HashSet<>(wordList);
if (!wordSet.contains(endWord)) return 0;

Set<String> beginSet = new HashSet<>();
Set<String> endSet = new HashSet<>();
Set<String> visited = new HashSet<>();

beginSet.add(beginWord);
endSet.add(endWord);
visited.add(beginWord);
visited.add(endWord);

int length = 1;

while (!beginSet.isEmpty() && !endSet.isEmpty()) {
// 总是从较小的集合开始扩展
if (beginSet.size() > endSet.size()) {
Set<String> temp = beginSet;
beginSet = endSet;
endSet = temp;
}

Set<String> nextSet = new HashSet<>();

for (String word : beginSet) {
char[] charArray = word.toCharArray();

for (int i = 0; i < charArray.length; i++) {
char originalChar = charArray[i];

for (char c = 'a'; c <= 'z'; c++) {
if (c == originalChar) continue;

charArray[i] = c;
String newWord = new String(charArray);

if (endSet.contains(newWord)) {
return length + 1;
}

if (wordSet.contains(newWord) && !visited.contains(newWord)) {
visited.add(newWord);
nextSet.add(newWord);
}
}

charArray[i] = originalChar;
}
}

beginSet = nextSet;
length++;
}

return 0;
}

/**
* LeetCode 279 - 完全平方数
* BFS求最短路径的变种
*/
public int numSquares(int n) {
if (n <= 0) return 0;

Queue<Integer> queue = new LinkedList<>();
Set<Integer> visited = new HashSet<>();
int[] squares = generateSquares(n);

queue.offer(n);
visited.add(n);
int level = 0;

while (!queue.isEmpty()) {
int size = queue.size();
level++;

for (int i = 0; i < size; i++) {
int current = queue.poll();

for (int square : squares) {
int next = current - square;

if (next < 0) break;
if (next == 0) return level;

if (!visited.contains(next)) {
visited.add(next);
queue.offer(next);
}
}
}
}

return n; // 最坏情况,全部由1组成
}

private int[] generateSquares(int n) {
int maxSquareRoot = (int) Math.sqrt(n);
int[] squares = new int[maxSquareRoot];
for (int i = 0; i < maxSquareRoot; i++) {
squares[i] = (i + 1) * (i + 1);
}
return squares;
}
}

4. 性能优化与高级技巧

4.1 双向BFS深度优化

/**
* 高级双向BFS实现
*/
public class AdvancedBidirectionalBFS {

public static int bidirectionalBFS(GraphNode start, GraphNode end) {
if (start == null || end == null) return -1;
if (start == end) return 0;

// 使用两个队列和两个访问集合
Queue<GraphNode> queueA = new LinkedList<>();
Queue<GraphNode> queueB = new LinkedList<>();
Map<GraphNode, Integer> visitedA = new HashMap<>(); // 记录节点和距离
Map<GraphNode, Integer> visitedB = new HashMap<>();

// 初始化
queueA.offer(start);
queueB.offer(end);
visitedA.put(start, 0);
visitedB.put(end, 0);

while (!queueA.isEmpty() && !queueB.isEmpty()) {
// 从较小队列扩展
int distance = expandQueue(queueA, visitedA, visitedB);
if (distance != -1) return distance;

distance = expandQueue(queueB, visitedB, visitedA);
if (distance != -1) return distance;
}

return -1;
}

private static int expandQueue(Queue<GraphNode> queue, 
Map<GraphNode, Integer> visitedFromThisSide,
Map<GraphNode, Integer> visitedFromOtherSide) {
if (queue.isEmpty()) return -1;

GraphNode current = queue.poll();
int currentDistance = visitedFromThisSide.get(current);

for (GraphNode neighbor : current.neighbors) {
if (!visitedFromThisSide.containsKey(neighbor)) {
// 检查是否在另一侧被访问过
if (visitedFromOtherSide.containsKey(neighbor)) {
return currentDistance + 1 + visitedFromOtherSide.get(neighbor);
}

visitedFromThisSide.put(neighbor, currentDistance + 1);
queue.offer(neighbor);
}
}

return -1;
}
}

4.2 启发式BFS(A*算法)

/**
* A*搜索算法 - BFS的启发式扩展
*/
public class AStarSearch {

static class NodeWithPriority implements Comparable<NodeWithPriority> {
GraphNode node;
int cost; // g(n):从起点到当前节点的实际代价
int heuristic; // h(n):到目标的估计代价
int total; // f(n) = g(n) + h(n)

public NodeWithPriority(GraphNode node, int cost, int heuristic) {
this.node = node;
this.cost = cost;
this.heuristic = heuristic;
this.total = cost + heuristic;
}

@Override
public int compareTo(NodeWithPriority other) {
return Integer.compare(this.total, other.total);
}
}

/**
* A*搜索实现
* @param start 起始节点
* @param end 目标节点
* @param heuristic 启发式函数
* @return 最短路径长度,-1表示不可达
*/
public static int aStarSearch(GraphNode start, GraphNode end, 
java.util.function.Function<GraphNode, Integer> heuristic) {
PriorityQueue<NodeWithPriority> openSet = new PriorityQueue<>();
Map<GraphNode, Integer> gScore = new HashMap<>(); // 实际代价
Map<GraphNode, GraphNode> cameFrom = new HashMap<>(); // 路径重建

// 初始化
gScore.put(start, 0);
openSet.offer(new NodeWithPriority(start, 0, heuristic.apply(start)));

while (!openSet.isEmpty()) {
NodeWithPriority current = openSet.poll();

if (current.node == end) {
return current.cost; // 找到目标
}

// 如果当前路径不是最优,跳过
if (current.cost > gScore.getOrDefault(current.node, Integer.MAX_VALUE)) {
continue;
}

for (GraphNode neighbor : current.node.neighbors) {
int tentativeGScore = gScore.get(current.node) + 1; // 假设边权为1

if (tentativeGScore < gScore.getOrDefault(neighbor, Integer.MAX_VALUE)) {
// 找到更优路径
cameFrom.put(neighbor, current.node);
gScore.put(neighbor, tentativeGScore);
int fScore = tentativeGScore + heuristic.apply(neighbor);
openSet.offer(new NodeWithPriority(neighbor, tentativeGScore, fScore - tentativeGScore));
}
}
}

return -1; // 不可达
}
}

5. 复杂度分析与工程实践

5.1 详细复杂度分析

时间复杂度:
  • 基础BFS:O(V + E)
    • 每个节点入队出队一次:O(V)
    • 每条边检查一次:O(E)
  • 矩阵BFS:O(M × N)
    • 每个单元格访问一次
  • 双向BFS:O(b^(d/2)),其中b是分支因子,d是深度
    • 比传统BFS的O(b^d)有显著提升
空间复杂度:
  • 最坏情况:O(V) - 所有节点都在队列中
  • 最佳情况:O(1) - 线性图
  • 平均情况:O(最大层宽度)

5.2 工程实践建议

/**
* 生产环境BFS最佳实践
*/
public class ProductionBFSBestPractices {

/**
* 带容量限制的BFS - 防止内存溢出
*/
public static List<Integer> bfsWithCapacityLimit(GraphNode start, int maxNodes) {
List<Integer> result = new ArrayList<>();
if (start == null) return result;

Queue<GraphNode> queue = new LinkedList<>();
Set<GraphNode> visited = new HashSet<>();
int processedNodes = 0;

queue.offer(start);
visited.add(start);

while (!queue.isEmpty() && processedNodes < maxNodes) {
GraphNode current = queue.poll();
result.add(current.val);
processedNodes++;

for (GraphNode neighbor : current.neighbors) {
if (!visited.contains(neighbor) && processedNodes < maxNodes) {
visited.add(neighbor);
queue.offer(neighbor);
}
}
}

return result;
}

/**
* 带超时控制的BFS
*/
public static List<Integer> bfsWithTimeout(GraphNode start, long timeoutMillis) {
List<Integer> result = new ArrayList<>();
if (start == null) return result;

Queue<GraphNode> queue = new LinkedList<>();
Set<GraphNode> visited = new HashSet<>();
long startTime = System.currentTimeMillis();

queue.offer(start);
visited.add(start);

while (!queue.isEmpty()) {
// 检查超时
if (System.currentTimeMillis() - startTime > timeoutMillis) {
System.out.println("BFS timeout after " + timeoutMillis + "ms");
break;
}

GraphNode current = queue.poll();
result.add(current.val);

for (GraphNode neighbor : current.neighbors) {
if (!visited.contains(neighbor)) {
visited.add(neighbor);
queue.offer(neighbor);
}
}
}

return result;
}

/**
* 并行BFS - 用于大规模图处理
*/
public static class ParallelBFS {
private final ExecutorService executor;

public ParallelBFS(int threadCount) {
this.executor = Executors.newFixedThreadPool(threadCount);
}

public List<Integer> parallelBFSTraversal(GraphNode start) {
// 简化的并行BFS实现思路
// 实际实现需要考虑更复杂的同步机制
List<Integer> result = Collections.synchronizedList(new ArrayList<>());
Queue<GraphNode> queue = new ConcurrentLinkedQueue<>();
Set<GraphNode> visited = ConcurrentHashMap.newKeySet();

queue.offer(start);
visited.add(start);

List<Future<?>> futures = new ArrayList<>();

while (!queue.isEmpty()) {
GraphNode current = queue.poll();
result.add(current.val);

// 并行处理邻居节点
for (GraphNode neighbor : current.neighbors) {
if (visited.add(neighbor)) {
queue.offer(neighbor);
}
}
}

return result;
}
}
}

6. 算法对比与选择指南

6.1 BFS vs DFS 深度对比

维度
BFS
DFS
数据结构
队列(FIFO)
栈(LIFO)
空间复杂度
O(宽) - 可能很大
O(深) - 通常较小
最短路径
保证找到最短路径
不一定是最短路径
完备性
是(如果解存在)
是(在有限图中)
适用场景
最短路径、层次遍历
拓扑排序、回溯、路径存在性
内存使用
较高(存储整层节点)
较低(存储单条路径)
实现复杂度
中等
简单(递归)

6.2 场景选择指南

选择BFS当:
  • 需要找到最短路径(无权图)
  • 图比较浅但很宽
  • 需要层次信息
  • 解可能在较浅层级
选择DFS当:
  • 内存受限
  • 需要找到任何解(不要求最短)
  • 图很深但较窄
  • 需要回溯或记录路径

7. 常见陷阱与调试技巧

7.1 常见错误模式

public class BFSCommonMistakes {

// 错误1:忘记标记访问导致无限循环
public static List<Integer> mistake1_infiniteLoop(GraphNode start) {
List<Integer> result = new ArrayList<>();
Queue<GraphNode> queue = new LinkedList<>();
// 缺少: Set<GraphNode> visited = new HashSet<>();

queue.offer(start);
// 缺少: visited.add(start);

while (!queue.isEmpty()) {
GraphNode current = queue.poll();
result.add(current.val);

for (GraphNode neighbor : current.neighbors) {
// 缺少访问检查,会导致重复访问
queue.offer(neighbor);
}
}

return result;
}

// 错误2:访问标记时机错误
public static List<Integer> mistake2_lateMarking(GraphNode start) {
List<Integer> result = new ArrayList<>();
Queue<GraphNode> queue = new LinkedList<>();
Set<GraphNode> visited = new HashSet<>();

queue.offer(start);
// 应该在入队时标记,而不是出队时

while (!queue.isEmpty()) {
GraphNode current = queue.poll();
visited.add(current); // 太晚了!可能导致重复入队
result.add(current.val);

for (GraphNode neighbor : current.neighbors) {
if (!visited.contains(neighbor)) {
queue.offer(neighbor);
// 应该在这里: visited.add(neighbor);
}
}
}

return result;
}
}

7.2 调试与验证工具

/**
* BFS调试工具类
*/
public class BFSDebugger {

/**
* 带日志的BFS,用于调试
*/
public static List<Integer> bfsWithDebug(GraphNode start) {
List<Integer> result = new ArrayList<>();
if (start == null) return result;

Queue<GraphNode> queue = new LinkedList<>();
Set<GraphNode> visited = new HashSet<>();
int step = 0;

queue.offer(start);
visited.add(start);
System.out.println("Step " + step + ": Enqueue " + start.val);

while (!queue.isEmpty()) {
GraphNode current = queue.poll();
result.add(current.val);
System.out.println("Step " + ++step + ": Process " + current.val);

for (GraphNode neighbor : current.neighbors) {
if (!visited.contains(neighbor)) {
visited.add(neighbor);
queue.offer(neighbor);
System.out.println("Step " + step + ": Enqueue neighbor " + neighbor.val);
}
}
}

return result;
}

/**
* 验证BFS结果的正确性
*/
public static boolean validateBFSResult(GraphNode start, List<Integer> result) {
if (start == null && result.isEmpty()) return true;
if (start == null || result.isEmpty()) return false;

// 检查起始节点
if (result.get(0) != start.val) return false;

// 检查访问顺序的层次性(简化验证)
Set<Integer> visited = new HashSet<>();
for (int nodeVal : result) {
if (visited.contains(nodeVal)) {
return false; // 重复访问
}
visited.add(nodeVal);
}

return true;
}
}

8. 总结与进阶学习

8.1 核心要点回顾

  1. BFS本质:层次遍历,保证最短路径(无权图)
  2. 实现关键:队列 + 访问标记
  3. 时间复杂度:O(V + E)
  4. 空间复杂度:O(V)
  5. 适用场景:最短路径、连通分量、层次遍历

8.2 进阶学习路径

  1. 加权图BFS:学习Dijkstra算法
  2. 启发式搜索:掌握A*算法
  3. 并行BFS:了解分布式图处理
  4. 动态BFS:学习在动态图中的BFS
  5. 近似BFS:大规模图的近似算法

8.3 推荐练习题目

初级(掌握基础):
  • LeetCode 102: 二叉树层次遍历
  • LeetCode 107: 二叉树层次遍历II
  • LeetCode 200: 岛屿数量
中级(应用扩展):
  • LeetCode 127: 单词接龙
  • LeetCode 279: 完全平方数
  • LeetCode 542: 01矩阵
高级(优化挑战):
  • LeetCode 1293: 网格中的最短路径
  • LeetCode 773: 滑动谜题
  • LeetCode 815: 公交路线
通过系统学习和实践,BFS将成为你解决图论问题的强大工具。记住:理解原理比记忆代码更重要,多思考为什么这样设计,而不仅仅是怎样实现。
http://www.dtcms.com/a/471533.html

相关文章:

  • 做网站需要icp吗网站建设dede模板免费
  • 好用的土木建筑网站汕头高端网站建设
  • MySQL数据库面试高频问题及解析
  • 怎么用自己的电脑做网站服务器爱企业工商信息查询系统
  • 无锡游戏网站建设公司作文生成器网站
  • .概述网站建设的基本流程哪个网站可以做鸟瞰图
  • 做网站要学云南免费网站建设
  • 杨浦专业做网站互联网服务平台待备案机动车
  • 购物网站设计模版自定义手机网站建设
  • XXL-Job入门:项目集成、任务编写与页面配置完整教程
  • 无人设备中继器的关键技术
  • 网站备案前置审批大学生创新创业大赛案例
  • 设计素材网站排版甘肃做网站价格
  • 天津做网站优化的公司php 做视频网站
  • 网站的开发流程分哪几步专业做俄语网站建设
  • Davinci工程讲解
  • 免费网站在线观看人数在哪买国有林场网站建设
  • 茂名哪里有网站开发公司网站建设教育平台
  • 学习SpringBoot
  • nas 可以做网站吗wordpress 文章付费查看
  • 标识设计公司网站公司做免费网站
  • 网页欣赏网站微信商城网站搭建
  • 企业网站备案是什么意思专业电商网站
  • 做it人经常逛的网站中国制造网下载
  • 国外免费外贸网站马关县网站建设
  • 广东基层团组织建设部网站甘肃省建设厅不动产网站
  • 微信连接微网站吗网址跳转网站
  • OpenSSH下载和安装教程(附安装包)
  • 北京欢迎您张家界seo优化方案
  • 签署网站建设协议新闻白城百度网站建设