用C语言实现用广度优先遍历求无权图的单源最短路径,要求写出详细的注释
时间: 2024-05-04 16:22:14 浏览: 109
Dijkstra算法求无向图单源最短路径(C语言实现)
4星 · 用户满意度95%
以下是使用C语言实现无权图的单源最短路径的示例代码,使用了广度优先遍历算法:
```c
#include <stdio.h>
#include <stdlib.h>
#define MAX_VERTEX_NUM 100 // 顶点数的最大值
typedef struct ArcNode { // 边结点
int adjvex; // 相邻顶点的下标
struct ArcNode *next; // 下一个边结点的指针
} ArcNode;
typedef struct { // 顶点结构体
int data; // 顶点的数据
ArcNode *first; // 第一个边结点的指针
} VNode;
typedef struct { // 无向图结构体
VNode vertex[MAX_VERTEX_NUM]; // 顶点数组
int vexnum; // 顶点数
int arcnum; // 边数
} Graph;
void BFS(Graph G, int v, int *dist, int *path) {
// 参数说明:
// G:无向图
// v:起始顶点的下标
// dist:记录每个顶点的最短距离
// path:记录每个顶点的前驱顶点
int visited[MAX_VERTEX_NUM] = {0}; // 标记数组,记录每个顶点是否已经被访问
visited[v] = 1; // 将起始顶点标记为已访问
dist[v] = 0; // 起始顶点到自身的距离为0
// 创建一个空队列
int queue[MAX_VERTEX_NUM] = {0};
int front = 0, rear = 0;
queue[rear++] = v; // 将起始顶点入队
// 遍历队列中的所有顶点
while (front < rear) {
int u = queue[front++]; // 出队一个顶点
ArcNode *p = G.vertex[u].first; // 获取该顶点的第一个邻接点
while (p) { // 遍历该顶点的所有邻接点
int w = p->adjvex; // 获取邻接点的下标
if (!visited[w]) { // 如果邻接点未被访问过
visited[w] = 1; // 标记为已访问
dist[w] = dist[u] + 1; // 更新最短距离
path[w] = u; // 记录前驱顶点
queue[rear++] = w; // 将邻接点入队
}
p = p->next; // 处理下一个邻接点
}
}
}
int main() {
Graph G;
int dist[MAX_VERTEX_NUM] = {0}; // 记录每个顶点的最短距离
int path[MAX_VERTEX_NUM] = {-1}; // 记录每个顶点的前驱顶点
int v; // 起始顶点的下标
// 读入顶点数和边数
scanf("%d %d", &G.vexnum, &G.arcnum);
// 读入每个顶点的数据
for (int i = 0; i < G.vexnum; i++) {
scanf("%d", &G.vertex[i].data);
G.vertex[i].first = NULL; // 初始化每个顶点的邻接表为空
}
// 读入每条边
for (int i = 0; i < G.arcnum; i++) {
int u, v;
scanf("%d %d", &u, &v);
// 添加一条从u到v的边
ArcNode *p = (ArcNode *) malloc(sizeof(ArcNode));
p->adjvex = v;
p->next = G.vertex[u].first;
G.vertex[u].first = p;
// 添加一条从v到u的边(无向图)
p = (ArcNode *) malloc(sizeof(ArcNode));
p->adjvex = u;
p->next = G.vertex[v].first;
G.vertex[v].first = p;
}
// 读入起始顶点的下标
scanf("%d", &v);
// 使用BFS算法求出每个顶点的最短距离和前驱顶点
BFS(G, v, dist, path);
// 输出每个顶点的最短距离和前驱顶点
for (int i = 0; i < G.vexnum; i++) {
printf("Vertex %d: distance=%d, path=", i, dist[i]);
int j = i;
while (j != -1) { // 输出从起始顶点到该顶点的路径
printf("%d", j);
j = path[j];
if (j != -1) {
printf("->");
}
}
printf("\n");
}
return 0;
}
```
在上述代码中,我们首先定义了一个无向图的数据结构 `Graph`,其中包含顶点数组 `vertex`,顶点数 `vexnum` 和边数 `arcnum` 三个成员变量。每个顶点由一个数据 `data` 和一个指向第一个邻接点的指针 `first` 组成。邻接点使用边结点 `ArcNode` 来表示,其中包含一个相邻顶点的下标 `adjvex` 和一个指向下一个邻接点的指针 `next`。
在 `BFS` 函数中,我们首先创建一个标记数组 `visited`,用于记录每个顶点是否已经被访问过。然后将起始顶点标记为已访问,并将起始顶点到自身的距离设为0。接着创建一个空队列,将起始顶点入队。然后使用 `while` 循环遍历队列中的所有顶点,对于每个顶点,遍历其所有邻接点,如果邻接点未被访问过,则将其标记为已访问,更新其最短距离和前驱顶点,并将其入队。最终,函数返回时, `dist` 数组中记录了每个顶点的最短距离, `path` 数组中记录了每个顶点的前驱顶点。
在 `main` 函数中,我们首先读入顶点数和边数,然后读入每个顶点的数据,以及每条边的两个顶点。根据输入的信息,我们建立起了一个无向图。然后读入起始顶点的下标,并调用 `BFS` 函数来求出每个顶点的最短距离和前驱顶点,并输出它们。
阅读全文