在计算机科学中,图(Graph)是一种非常重要的非线性数据结构,广泛应用于社交网络、路径规划、任务调度等领域。对于初学者来说,理解图的表示方法是学习图算法的第一步。本文将用通俗易懂的方式,带你了解在C语言中如何表示图,并重点讲解两种最常用的图的存储方式:邻接矩阵和邻接表。
图由顶点(Vertex)和边(Edge)组成。顶点代表对象,边代表对象之间的关系。例如,在社交网络中,每个人是一个顶点,朋友关系就是边。
邻接矩阵(Adjacency Matrix)是一种使用二维数组来表示图的方法。假设图有 n 个顶点,我们就创建一个 n × n 的二维数组 graph[n][n]。
i 和顶点 j 之间有边,则 graph[i][j] = 1(或边的权重);graph[i][j] = 0。邻接矩阵适合表示稠密图(即边很多的图),因为它的空间复杂度固定为 O(n²)。
#include <stdio.h>#define MAX_VERTICES 10int main() { int graph[MAX_VERTICES][MAX_VERTICES] = {0}; // 初始化为0 int vertices = 5; // 添加边:0-1, 0-4, 1-2, 1-3, 1-4, 2-3, 3-4 graph[0][1] = graph[1][0] = 1; // 无向图,对称 graph[0][4] = graph[4][0] = 1; graph[1][2] = graph[2][1] = 1; graph[1][3] = graph[3][1] = 1; graph[1][4] = graph[4][1] = 1; graph[2][3] = graph[3][2] = 1; graph[3][4] = graph[4][3] = 1; // 打印邻接矩阵 printf("邻接矩阵表示:\n"); for (int i = 0; i < vertices; i++) { for (int j = 0; j < vertices; j++) { printf("%d ", graph[i][j]); } printf("\n"); } return 0;} 邻接表(Adjacency List)使用链表(或动态数组)来存储每个顶点的相邻顶点。它更适合表示稀疏图(边较少的图),因为它只存储实际存在的边,空间复杂度为 O(V + E),其中 V 是顶点数,E 是边数。
由于C语言没有内置的链表,我们需要自己定义结构体:
#include <stdio.h>#include <stdlib.h>// 定义链表节点struct Node { int vertex; struct Node* next;};// 创建新节点struct Node* createNode(int v) { struct Node* newNode = malloc(sizeof(struct Node)); newNode->vertex = v; newNode->next = NULL; return newNode;}// 图结构struct Graph { int numVertices; struct Node** adjLists; // 指向指针的指针,每个元素是一个链表头};// 创建图struct Graph* createGraph(int vertices) { struct Graph* graph = malloc(sizeof(struct Graph)); graph->numVertices = vertices; graph->adjLists = malloc(vertices * sizeof(struct Node*)); for (int i = 0; i < vertices; i++) graph->adjLists[i] = NULL; return graph;}// 添加边void addEdge(struct Graph* graph, int src, int dest) { // 无向图:src -> dest struct Node* newNode = createNode(dest); newNode->next = graph->adjLists[src]; graph->adjLists[src] = newNode; // 无向图:dest -> src newNode = createNode(src); newNode->next = graph->adjLists[dest]; graph->adjLists[dest] = newNode;}// 打印邻接表void printGraph(struct Graph* graph) { for (int v = 0; v < graph->numVertices; v++) { struct Node* temp = graph->adjLists[v]; printf("顶点 %d: ", v); while (temp) { printf("%d -> ", temp->vertex); temp = temp->next; } printf("NULL\n"); }}int main() { struct Graph* graph = createGraph(5); addEdge(graph, 0, 1); addEdge(graph, 0, 4); addEdge(graph, 1, 2); addEdge(graph, 1, 3); addEdge(graph, 1, 4); addEdge(graph, 2, 3); addEdge(graph, 3, 4); printGraph(graph); return 0;} | 特性 | 邻接矩阵 | 邻接表 |
|---|---|---|
| 空间复杂度 | O(V²) | O(V + E) |
| 查询两点是否有边 | O(1) | O(degree) |
| 适合图类型 | 稠密图 | 稀疏图 |
通过本文,你已经掌握了C语言图的表示方法中最核心的两种:邻接矩阵和邻接表。邻接矩阵简单直观但占用空间大;邻接表节省空间但实现稍复杂。根据你的应用场景(比如图的密度、操作频率等),可以选择合适的表示方式。
记住,无论是学习邻接矩阵还是邻接表,动手写代码是掌握的关键。建议你复制上面的代码,在自己的编译器中运行并修改,加深理解。
希望这篇教程能帮助你顺利入门图论!如果你觉得有用,欢迎分享给其他正在学习图的数据结构的朋友。
本文由主机测评网于2025-12-02发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/2025121901.html