👋 Hi, I’m @Beast Cheng
👀 I’m interested in photography, hiking, landscape…
🌱 I’m currently learning python, javascript, kotlin…
📫 How to reach me --> 458290771@qq.com
喜欢《数据结构》部分笔记的小伙伴可以订阅专栏,今后还会不断更新。🧑💻
感兴趣的小伙伴可以点一下订阅、收藏、关注!🚀
谢谢大家!🙏
与树的广度优先遍历之间的联系
树的广度优先遍历[[5.4.3 树和森林的遍历]]
图的广度优先遍历和树类似
但是对于图来说:搜索相邻的结点时,有可能搜到已经访问过的结点
解决方法:对已经访问过的结点打上标记就行了
算法实现
广度优先遍历(BFS)要点:
- 找到与一个顶点相邻的所有顶点
- 标记哪些顶点被访问过
- 需要一个辅助队列
bool visited[MAX_VERTEX_NUM]; // 标记访问数组
// 广度优先遍历
void BFS(Graph G, int v){ // 从顶点v出发,广度优先遍历图G
visit(v); // 访问初始顶点v
visited[v] = TRUE; // 对v做已访问标记
EnQueue(Q, v); // 顶点v入队列Q
while(!isEmpty(Q)){
DeQueue(Q, v); // 顶点v出队列
for(w=FirstNeighbor(G, v); w>=0; w=NextNeighbor(G, v, w)){
// 检测v所有邻接点
if(!visited[w]){ // w是v的尚未访问的邻接顶点
visit(w); // 访问顶点w
visited[w] = TRUE; // 对w做已访问标记
EnQueue(Q, w); // 顶点w入队列
}
}
}
}
算法存在的问题
如果是非连通图,无法遍历完所有的结点
解决方法:增加一段代码
void BFSTraverse(Graph G){ // 对图G进行广度优先遍历
for(i=0; i<G.vexnum; ++i)
visited[i] = FALSE; // 访问标记数组初始化
InitQueue(Q); // 初始化辅助队列Q
for(i=0; i<G.vexnum; ++i) // 从0号顶点开始遍历
if(!visited[i]) // 对每个连通分量调用一次BFS
BFS(G, i); // vi从未访问过,从vi开始进行BFS
}
复杂度分析
邻接矩阵存储的图:
访问
∣
V
∣
|V|
∣V∣ 个顶点都需要
O
(
∣
V
∣
)
O(|V|)
O(∣V∣) 的时间
查找每个顶点的邻接点都需要
O
(
∣
V
∣
)
O(|V|)
O(∣V∣) 的时间,而总共有
∣
V
∣
|V|
∣V∣ 个顶点
时间复杂度
=
O
(
∣
V
∣
2
)
=O(|V|^2)
=O(∣V∣2)
邻接表存储的图:
访问
∣
V
∣
|V|
∣V∣ 个顶点都需要
O
(
∣
V
∣
)
O(|V|)
O(∣V∣) 的时间
查找各个顶点的邻接点共需要
O
(
∣
E
∣
)
O(|E|)
O(∣E∣) 的时间
时间复杂度
=
O
(
∣
V
∣
+
∣
E
∣
)
=O(|V|+|E|)
=O(∣V∣+∣E∣)
结论:对于 无向图,调用 BFS 函数的次数 = 连通分量数
广度优先生成树
广度优先生成树由广度优先遍历过程确定
由于邻接表的表示方式不唯一,因此基于邻接表的广度优先生成树也不唯一
广度优先生成森林
对非连通图的广度优先遍历,可得到广度优先生成森林