树和图的广度优先遍历区别
树的广度优先遍历:
图的广度优先遍历:
代码:
注:以下代码只适合连通图
#include <stdio.h>
#include <stdbool.h>
#define MAX_VERTEX_NUM 100
typedef struct ArcNode {
int adjvex; // 该边所指向的顶点的位置
struct ArcNode* nextarc; // 指向下一条边的指针
} ArcNode;
typedef struct VNode {
char data; // 顶点信息
ArcNode* firstarc; // 指向第一条边的指针
} VNode, AdjList[MAX_VERTEX_NUM];
typedef struct {
AdjList vertices;
int vexnum, arcnum; // 图的顶点数和边数
} ALGraph;
bool visited[MAX_VERTEX_NUM]; // 访问标记数组
// 访问顶点的函数
void visit(int v) {
printf("%d ", v);
}
// 判断队列是否为空
bool isEmpty(int front, int rear) {
return front == rear;
}
// 入队操作
void EnQueue(int* queue, int rear, int v) {
queue[rear++] = v;
}
// 出队操作
void DeQueue(int* queue, int* front, int* v) {
*v = queue[(*front)++];
}
// 返回顶点v的第一个邻接点
int FirstNeighbor(ALGraph* G, int v) {
if (G->vertices[v].firstarc) {
return G->vertices[v].firstarc->adjvex;
}
return -1;
}
// 返回顶点v相对于w的下一个邻接点
int NextNeighbor(ALGraph* G, int v, int w) {
ArcNode* p = G->vertices[v].firstarc;
while (p && p->adjvex != w) {
p = p->nextarc;
}
if (p && p->nextarc) {
return p->nextarc->adjvex;
}
return -1;
}
// 广度优先遍历
void BFS(ALGraph* G, int v) {
int queue[MAX_VERTEX_NUM]; // 辅助队列
int front = 0, rear = 0; // 队列的头尾指针
int w;
visit(v); // 访问初始顶点v
visited[v] = true; // 对v做已访问标记
EnQueue(queue, rear, v); // 顶点v入队列
while (!isEmpty(front, rear)) {
DeQueue(queue, &front, &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(queue, rear, w); // 顶点w入队列
}
}
}
}
// 主函数,用于演示
int main() {
// 假设图G已经被正确初始化
ALGraph G;
// ... 初始化图G ...
// 初始化访问标记数组
for (int i = 0; i < G.vexnum; ++i) {
visited[i] = false;
}
// 从顶点0开始进行广度优先遍历
BFS(&G, 0);
return 0;
}
练习:
遍历序列的可变性
BFS算法(优化版可遍历非连通图)
代码:
bool visited[MAX_VERTEX_NUM];//访问标记数组
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
}
//广度优先遍历
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=FirsitNeighbor(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入队列
}
}
}
结论:对于无向图,调用BFS函数的次数=连通分量数
复杂度分析
空间复杂度:
时间复杂度:
广度优先生成树
广度优先生成森林
练习:有向图的BFS过程