数据结构(6_3_1)——图的广度优先遍历

树和图的广度优先遍历区别

 树的广度优先遍历:

图的广度优先遍历: 

代码:

 注:以下代码只适合连通图

#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过程

 

总结 :

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值