/** * File: graph_adjacency_list.c * Created Time: 2023-07-07 * Author: NI-SW (947743645@qq.com) */ #include "../utils/common.h" // 假设节点最大数量为 100 #define MAX_SIZE 100 /* 节点结构体 */ typedef struct AdjListNode { Vertex *vertex; // 顶点 struct AdjListNode *next; // 后继节点 } AdjListNode; /* 基于邻接表实现的无向图类 */ typedef struct { AdjListNode *heads[MAX_SIZE]; // 节点数组 int size; // 节点数量 } GraphAdjList; /* 构造函数 */ GraphAdjList *newGraphAdjList() { GraphAdjList *graph = (GraphAdjList *)malloc(sizeof(GraphAdjList)); if (!graph) { return NULL; } graph->size = 0; for (int i = 0; i < MAX_SIZE; i++) { graph->heads[i] = NULL; } return graph; } /* 析构函数 */ void delGraphAdjList(GraphAdjList *graph) { for (int i = 0; i < graph->size; i++) { AdjListNode *cur = graph->heads[i]; while (cur != NULL) { AdjListNode *next = cur->next; if (cur != graph->heads[i]) { free(cur); } cur = next; } free(graph->heads[i]->vertex); free(graph->heads[i]); } free(graph); } /* 查找顶点对应的节点 */ AdjListNode *findNode(GraphAdjList *graph, Vertex *vet) { for (int i = 0; i < graph->size; i++) { if (graph->heads[i]->vertex == vet) { return graph->heads[i]; } } return NULL; } /* 添加边辅助函数 */ void addEdgeHelper(AdjListNode *head, Vertex *vet) { AdjListNode *node = (AdjListNode *)malloc(sizeof(AdjListNode)); node->vertex = vet; // 头插法 node->next = head->next; head->next = node; } /* 添加边 */ void addEdge(GraphAdjList *graph, Vertex *vet1, Vertex *vet2) { AdjListNode *head1 = findNode(graph, vet1); AdjListNode *head2 = findNode(graph, vet2); assert(head1 != NULL && head2 != NULL && head1 != head2); // 添加边 vet1 - vet2 addEdgeHelper(head1, vet2); addEdgeHelper(head2, vet1); } /* 删除边辅助函数 */ void removeEdgeHelper(AdjListNode *head, Vertex *vet) { AdjListNode *pre = head; AdjListNode *cur = head->next; // 在链表中搜索 vet 对应节点 while (cur != NULL && cur->vertex != vet) { pre = cur; cur = cur->next; } if (cur == NULL) return; // 将 vet 对应节点从链表中删除 pre->next = cur->next; // 释放内存 free(cur); } /* 删除边 */ void removeEdge(GraphAdjList *graph, Vertex *vet1, Vertex *vet2) { AdjListNode *head1 = findNode(graph, vet1); AdjListNode *head2 = findNode(graph, vet2); assert(head1 != NULL && head2 != NULL); // 删除边 vet1 - vet2 removeEdgeHelper(head1, head2->vertex); removeEdgeHelper(head2, head1->vertex); } /* 添加顶点 */ void addVertex(GraphAdjList *graph, Vertex *vet) { assert(graph != NULL && graph->size < MAX_SIZE); AdjListNode *head = (AdjListNode *)malloc(sizeof(AdjListNode)); head->vertex = vet; head->next = NULL; // 在邻接表中添加一个新链表 graph->heads[graph->size++] = head; } /* 删除顶点 */ void removeVertex(GraphAdjList *graph, Vertex *vet) { AdjListNode *node = findNode(graph, vet); assert(node != NULL); // 在邻接表中删除顶点 vet 对应的链表 AdjListNode *cur = node, *pre = NULL; while (cur) { pre = cur; cur = cur->next; free(pre); } // 遍历其他顶点的链表,删除所有包含 vet 的边 for (int i = 0; i < graph->size; i++) { cur = graph->heads[i]; pre = NULL; while (cur) { pre = cur; cur = cur->next; if (cur && cur->vertex == vet) { pre->next = cur->next; free(cur); break; } } } // 将该顶点之后的顶点向前移动,以填补空缺 int i; for (i = 0; i < graph->size; i++) { if (graph->heads[i] == node) break; } for (int j = i; j < graph->size - 1; j++) { graph->heads[j] = graph->heads[j + 1]; } graph->size--; free(vet); } /* 打印邻接表 */ void printGraph(const GraphAdjList *graph) { printf("邻接表 =\n"); for (int i = 0; i < graph->size; ++i) { AdjListNode *node = graph->heads[i]; printf("%d: [", node->vertex->val); node = node->next; while (node) { printf("%d, ", node->vertex->val); node = node->next; } printf("]\n"); } }