图的广度优先搜索
广度优先搜索(Breadth-First Search, BFS)简单来说就是利用队列结构,将邻接点依次加入队列中,将一个顶点的邻接点都遍历完成后再遍历邻接点的邻接点。
基本思想
广度优先搜索类似于树的层次遍历。
- 首先访问图中某一个指定的出发点 vᵢ。
- 然后依次访问 vᵢ 的所有邻接点 vᵢ₁, vᵢ₂, …, vᵢₜ。
- 再依次以 vᵢ₁, vᵢ₂, …, vᵢₜ 为顶点,访问各顶点未被访问的邻接点,依此类推,直到图中所有顶点均被访问为止。
- 若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。
算法实现
邻接矩阵形式
void BFS(int i) { // 图用邻接矩阵表示
int i, j;
SETNULL(Q);
ENQUEUE(Q, i); // 当前访问结点入队
while (!EMPTY(Q)) {
i = DEQUEUE(Q); // 让当前结点出队
for (j = 0; j < n; j++) { // 访问这一行所有结点
if ((g.arcs[i][j] == 1) && (!visited[j])) {
// 如果当前结点有边且下一结点未被访问
visited[j] = TRUE;
ENQUEUE(Q, j);
}
}
}
}邻接表形式
void BFSL(int i) { // 图用邻接表表示
int i;
edgenode *p;
SETNULL(Q);
ENQUEUE(Q, i);
visited[i] = TRUE;
while (!EMPTY(Q)) {
i = DEQUEUE(Q);
p = g[i].link;
while (p != NULL) { // 访问 p 的整个链
if (!visited[p->adjvex]) {
visited[p->adjvex] = TRUE;
ENQUEUE(Q, p->adjvex);
}
p = p->next;
}
}
}复杂度分析
- 如果使用邻接矩阵,对于每一个被访问过的顶点,循环要检测矩阵中的 n 个元素,总的时间代价为 O(n²)。
- 如果使用邻接表,则时间复杂度为 O(n + e)。
这里复杂度的区别在深度优先搜索上也是一样的。这是因为对于邻接矩阵形式,无法直接得到一个顶点的邻接点,必须要遍历以该点为横坐标的所有值并一一与 1 比较来判断邻接点;而对于邻接表可以直接知道邻接点的稀疏表示,进而快速拿到一个顶点的邻接点信息。

链接到
- 上一个知识点:7.4 图的深度优先搜索
- 下一个知识点:7.6 生成树和最小生成树
- 相关知识点:5.3 广度优先搜索