图的表示
图(Graph)是最通用的非线性数据结构——一组顶点(Vertex, V)和连接它们的边(Edge, E),记作 G = (V, E)。它统一了链表(一条链即一条路径)、树(无环连通图)、网格(二维顶点加相邻边)等结构:链表是「一度图」、树是「无环连通无向图」、网格是「顶点按行列编号、边连相邻格」的特殊图。当你需要刻画关系(社交网络的好友、地图的道路、网页的链接、任务的依赖)时,图几乎是唯一选择。
图的表示本身不涉及算法,而是回答一个问题:给定 V 个顶点、E 条边,用什么数据结构把它们装起来? 三种主流答案各有取舍——邻接矩阵用 n×n 二维数组、a[i][j]=1(或权重)表示边,查边 O(1) 但 空间 O(n²),适合稠密图与需要 O(1) 判定边存在(如 Floyd 多源最短路)的场景;邻接表给每个顶点挂一条链表(或动态数组)存它的邻居,空间 O(V+E) 但查边要 O(度),是稀疏图与 BFS/DFS/Dijkstra 的标配;边集数组只存一条条边 {u, v, w},空间 O(E)、适合「按边处理」的算法(Kruskal 最小生成树、Bellman-Ford)。一句话总纲:稠密选矩阵、稀疏选表、按边选边集数组。
评价
优点
- 表达力强:图能刻画任意二元关系——顶点当实体、边当关系,社交/路网/依赖/调用图都能用同一套模型,链表/树/网格都是它的特例。
- 三种表示互补:邻接矩阵(查边 O(1))、邻接表(省空间 O(V+E))、边集数组(按边遍历)各有擅长面,工程上按场景选型即可兼顾时空。
- 算法生态完整:一旦存好,BFS/DFS/Dijkstra/Prim/Kruskal/拓扑排序都有现成且高效的实现——本叶解决「怎么存」,是后续图算法的前置。
- 易于加权与定向:矩阵存权重、表存
[邻居, 权重]即可支持带权图;有向图只存「出边」、无向图双向各存一次,扩展自然。
缺点
- 空间开销大(矩阵):邻接矩阵 O(n²) 对稀疏图(如社交网,每人几百好友 vs 上亿用户)是灾难——一亿顶点要 10¹⁶ 个槽位,根本存不下。
- 查边慢(邻接表):判定
(u,v)是否有边要扫 u 的整个邻居链表,O(度),不如矩阵的 O(1)。 - 细节多、易错:无向图一条边要存两次(忘记会丢边/方向反了);自环(
a[v][v])、重边(平行边)需特殊处理;带权图的权重存法因表示而异。
本叶地图
- 入门 —— 图的定义 G=(V,E)、有向/无向、带权/无权、稠密/稀疏、度(入度出度)、路径/环/连通分量、树是特殊的图
- 三种表示法 —— 邻接矩阵(n×n 查边 O(1) 空间 O(n²))、邻接表(空间 O(V+E))、边集数组(Kruskal 用)、三者对比、稠密选矩阵稀疏选表
- 工程实现与选型 —— 邻接表 JS/Python 实现、有向/无向/带权存法、输入格式、矩阵 vs 表选型、十字链表/邻接多重表引入
- 参考 —— 三种表示对比大表、代码模板、选型决策树、易错点(无向图边存两次/自环/重边)
交互演示
- 图的表示可视化演示 —— 邻接矩阵与邻接表的空间布局对比