以邻接表作存储结构,编写程序对给定的无向图G(包含n个顶点,编号为0至n-1
)进行广度优先遍历,并在遍历的过程中计算图G的连通分量个数及边的数目。
本题限定在遍历过程中,如果同时出现多个待访问的顶点,则优先选择编号最小
的一个进行访问,以顶点0
为遍历起点。
邻接表的类型描述
#define MaxVexNum 20 //最大顶点数
typedef struct ArcNode //表结点定义
{
int adjvex;
struct ArcNode *nextarc;
}ArcNode;
typedef struct
{
ArcNode *vertices[MaxVexNum];
int vernum, arcnum;
}ALGraph;
输入格式:
第一行输入图的顶点数
和边数e
。
接下来共e行
。每行代表一条边,输入边依附的两个顶点的编号
。用头插法建邻接表,各边按第一个顶点编号升序
输入,第一个顶点相同时按第二个顶点降序
输入。注意:边不能重复输入。
输出格式:
输出分三行
- 第一行 广度优先遍历序列。序列中每个顶点编号后跟一个空格。
- 第二行 连通分量个数
- 第三行 边数
对于下面给出的无向图G
输入样例:
9 8
0 2
0 1
1 3
2 6
2 5
3 4
5 6
7 8
输出样例:
0 1 2 3 5 6 4 7 8
2
8
#include <stdio.h>
#include <stdlib.h>
#define MaxVexNum 20
typedef struct ArcNode
{
int adjvex;
struct ArcNode *nextarc;
} ArcNode;
typedef struct
{
ArcNode *vertices[MaxVexNum];
int vernum, arcnum;
} ALGraph;
int visited[MaxVexNum]; // 记录顶点是否被访问过
// 队列结构
typedef struct
{
int data[MaxVexNum];
int front, rear;
} Queue;
// 初始化队列
void InitQueue(Queue *Q)
{
Q->front = Q->rear = 0;
}
// 判断队列是否为空
int IsEmpty(Queue *Q)
{
return Q->front == Q->rear;
}
// 入队
void EnQueue(Queue *Q, int value)
{
Q->data[Q->rear++] = value;
}
// 出队
int DeQueue(Queue *Q)
{
return Q->data[Q->front++];
}
// 广度优先遍历
void BFS(ALGraph *G, int v)
{
Queue Q;
InitQueue(&Q);
printf("%d ", v);
visited[v] = 1;
EnQueue(&Q, v);
while (!IsEmpty(&Q))
{
int front = DeQueue(&Q);
for (ArcNode *p = G->vertices[front]; p; p = p->nextarc)
{
int adjvex = p->adjvex;
if (!visited[adjvex])
{
printf("%d ", adjvex);
visited[adjvex] = 1;
EnQueue(&Q, adjvex);
}
}
}
}
int main()
{
ALGraph G;
int vex1, vex2;
// 输入图的顶点数和边数
scanf("%d %d", &G.vernum, &G.arcnum);
// 初始化邻接表
for (int i = 0; i < G.vernum; ++i)
{
G.vertices[i] = NULL;
}
// 输入边的信息,构建邻接表
for (int k = 0; k < G.arcnum; ++k)
{
scanf("%d %d", &vex1, &vex2);
// 创建ArcNode结点
ArcNode *node = (ArcNode *)malloc(sizeof(ArcNode));
node->adjvex = vex2;
node->nextarc = G.vertices[vex1];
G.vertices[vex1] = node;
// 由于是无向图,需要在vex2处再插入一条边
ArcNode *node2 = (ArcNode *)malloc(sizeof(ArcNode));
node2->adjvex = vex1;
node2->nextarc = G.vertices[vex2];
G.vertices[vex2] = node2;
}
// 初始化visited数组
for (int i = 0; i < G.vernum; ++i)
{
visited[i] = 0;
}
// 广度优先遍历
int connectedComponents = 0;
for (int i = 0; i < G.vernum; ++i)
{
if (!visited[i])
{
BFS(&G, i);
++connectedComponents;
}
}
printf("\n");
// 计算边的数目
int edges = 0;
for (int i = 0; i < G.vernum; ++i)
{
ArcNode *p = G.vertices[i];
while (p)
{
++edges;
p = p->nextarc;
}
}
edges /= 2; // 由于是无向图,每条边被计算两次
// 输出连通分量个数和边的数目
printf("%d\n%d\n", connectedComponents, edges);
// 释放内存
for (int i = 0; i < G.vernum; ++i)
{
ArcNode *p = G.vertices[i];
while (p)
{
ArcNode *temp = p;
p = p->nextarc;
free(temp);
}
}
return 0;
}