在计算机科学中,图是一种重要的抽象数据结构,广泛应用于各种领域,如社交网络分析、路由算法等。图通常包含若干个顶点(Vertex)和连接顶点的边(Edge)。有两种常见的图的表示方式:邻接矩阵和邻接表。本文主要讲解如何通过邻接表来表示一个图。
#include <stdio.h>
#include <stdlib.h>
#define MaxVertex 5 // 图的最大顶点数
typedef char E; // 定义元素类型为字符
// 头节点结构体,存储顶点的元素和指向下一个节点的指针
struct HeadNode {
E element; // 顶点元素
struct Node *next; // 指向下一个节点的指针
};
// 节点结构体,存储指向下一个节点的指针和邻接的顶点
typedef struct Node {
int nextVertex; // 存储邻接顶点的索引
struct Node *next; // 指向下一个节点的指针
} *Node;
// 邻接表结构体,包含顶点数量、边数量和顶点数组
typedef struct AdjacencyGraph {
int vertexCount; // 顶点数量
int edgeCount; // 边的数量
struct HeadNode vertex[MaxVertex]; // 存储每个顶点的头节点
} *Graph;
// 初始化邻接表,创建一个空图
Graph create() {
Graph graph = malloc(sizeof(struct AdjacencyGraph)); // 分配内存
graph->vertexCount = graph->edgeCount = 0; // 顶点和边的初始数量为0
return graph; // 返回图的指针
}
// 向图中添加顶点
void addVertex(Graph graph, E e) {
graph->vertex[graph->vertexCount].element = e; // 将元素e添加到vertex数组的当前索引位置
graph->vertex[graph->vertexCount].next = NULL; // 当前顶点的下一个节点为空
graph->vertexCount++; // 顶点数量增加
}
// 向图中添加边,连接顶点a和顶点b
void addEdge(Graph graph, int a, int b) {
Node node = graph->vertex[a].next; // 获取顶点a的下一个节点
Node newnode = malloc(sizeof(struct Node)); // 创建一个新的节点
newnode->next = NULL; // 新节点的next指针为空
newnode->nextVertex = b; // 新节点存储的邻接顶点是b
if (!node) { // 如果a没有邻接顶点
graph->vertex[a].next = newnode; // 将b直接添加为a的邻接顶点
} else { // 如果a已经有邻接顶点
do {
if (node->nextVertex == b) return; // 如果b已经是a的邻接顶点,则不重复添加
if (node->next) node = node->next; // 否则遍历下一个节点
else break;
} while (1);
node->next = newnode; // 将新节点插入到a的邻接顶点链表中
}
graph->edgeCount++; // 边的数量增加
}
// 打印图的邻接表
void printGraph(Graph graph) {
for (int i = 0; i < graph->vertexCount; i++) { // 遍历所有顶点
printf("%d | %c", i, graph->vertex[i].element); // 打印顶点的索引和元素
Node node = graph->vertex[i].next; // 获取当前顶点的第一个邻接节点
while (node) { // 如果当前顶点有邻接节点
printf(" -> %d", node->nextVertex); // 打印当前节点的邻接顶点
node = node->next; // 移动到下一个邻接节点
}
printf("\n");
}
}
// 主函数
int main(void) {
Graph graph = create(); // 创建图
// 添加顶点A到D
for (int c = 'A'; c <= 'D'; ++c)
addVertex(graph, (char)c); // 将字符A到D添加为顶点
// 添加边
addEdge(graph, 0, 1); // A -> B
addEdge(graph, 1, 2); // B -> C
addEdge(graph, 2, 3); // C -> D
addEdge(graph, 3, 0); // D -> A
addEdge(graph, 2, 0); // C -> A
printGraph(graph); // 打印邻接表
}