图的基本概念与存储结构
含AI生成内容
图的基本概念与存储结构
基本概念
图(Graph)G 由顶点集 V和边集 E组成,记为 G = (V, E)。顶点之间的关系是任意的——任意两个顶点之间都可能存在边,这是图与树、线性表的本质区别。
图的基本分类
| 分类标准 | 类型 | 说明 |
|---|---|---|
| 边的方向 | 无向图 | 边 (v, w) 无方向,(v, w) 与 (w, v) 等价 |
| 有向图 | 边称为弧 <v, w>,v 是弧尾,w 是弧头,<v, w> != <w, v> | |
| 边数上限 | 简单图 | 不存在重复边和自环(408 默认讨论简单图) |
| 多重图 | 允许两顶点间有多条边或存在自环 | |
| 是否带权 | 无权图 | 边仅表示关系存在 |
| 带权图(网) | 边附带权值,表示距离、代价等 |
完全图
边数达到上限的简单图称为完全图:
| 图类型 | 边数公式 | 说明 |
|---|---|---|
| 无向完全图 K_n | n(n-1)/2 | 每对顶点之间恰有一条边 |
| 有向完全图 | n(n-1) | 每对顶点之间有方向相反的两条弧 |
- 子图:G’ = (V’, E’),满足 V’ ⊆ V 且 E’ ⊆ E(注意 E’ 中的边关联的顶点必须在 V’ 中)
- 生成子图:V’ = V 的子图,即包含全部顶点的子图
易错:V 的任意子集和 E 的任意子集不一定能构成子图——E’ 中的边所关联的顶点必须在 V’ 中。
度(Degree)
无向图:顶点 v 的度 TD(v) = 与 v 关联的边数。
有向图:
- 入度 ID(v):以 v 为弧头的弧的数量
- 出度 OD(v):以 v 为弧尾的弧的数量
- 度 TD(v) = ID(v) + OD(v)
握手定理(高频考点)
| 图类型 | 公式 | 说明 |
|---|---|---|
| 无向图 | ∑TD(v) = 2e | 每条边贡献 2 度 |
| 有向图 | ∑ID(v) = ∑OD(v) = e | 每条弧贡献 1 入度 + 1 出度 |
其中 e 为边(弧)的数量。该公式是选择题中求边数或度数的核心工具。
连通性
无向图的连通性
- 连通:顶点 v 到 w 之间存在路径
- 连通图:任意两个顶点都连通
- 连通分量:无向图中的极大连通子图
| 条件 | 说明 |
|---|---|
| 连通图至少 n-1 条边 | 边数 < n-1 一定不连通 |
| n-1 条边不一定连通 | 可能有孤立顶点 |
| 边数 > (n-1)(n-2)/2 则一定连通 | 利用完全图反证 |
有向图的连通性
- 强连通:顶点 v 到 w 和 w 到 v 之间都存在路径
- 强连通图:任意两个顶点都强连通
- 强连通图至少需要 n 条弧(构成一个环)
- 强连通分量:有向图中的极大强连通子图
易错:“连通”(无向图)与”强连通”(有向图)不同。n 个顶点的强连通图至少需要 n 条边(构成一个环)。
连通分量与强连通分量
连通分量(无向图):无向图中的极大连通子图。连通图只有一个连通分量(即其自身),非连通图有多个。“极大”的含义:不能再加入更多的顶点和边使其仍然连通。
强连通分量(有向图):有向图中的极大强连通子图。任何一个顶点本身构成一个强连通分量。求强连通分量的方法:对图进行两次 DFS(Kosaraju 算法 / Tarjan 算法)。
二部图(二分图)
二部图(Bipartite Graph):顶点集 V 可分为两个互不相交的子集 V1 和 V2,图中每条边的两个端点分别属于 V1 和 V2。
判定定理:图 G 是二部图 ⟺ G 中不含奇数长度的回路。
完全二部图 K(m,n):V1 中每个顶点与 V2 中每个顶点都有边,共 m × n 条边。
边数公式速查
| 图类型 | 边数公式/范围 | 说明 |
|---|---|---|
| 无向完全图 K_n | n(n-1)/2 | 每对顶点一条边 |
| 有向完全图 | n(n-1) | 每对顶点两条弧 |
| 无向连通图 | n-1 ≤ e ≤ n(n-1)/2 | 最少为树,最多为完全图 |
| 强连通图 | n ≤ e ≤ n(n-1) | 最少构成一个环 |
| 完全二部图 K(m,n) | m × n | V1 有 m 个,V2 有 n 个 |
| 无向图度数之和 | 2e | 握手定理 |
| 有向图入度之和 | e | 等于出度之和 |
四种存储结构
邻接矩阵
存储方式:用二维数组 A[i][j] 表示顶点 i 与 j 的关系。无向图的邻接矩阵是对称矩阵。
无权图:A[i][j] = 1 表示存在边,0 表示不存在。
带权图:A[i][j] = w 表示边权,∞ 表示不存在边。
#define MaxVertexNum 100typedef struct { char vex[MaxVertexNum]; int edge[MaxVertexNum][MaxVertexNum]; int vexNum, edgeNum;} MGraph;度的计算:
- 无向图:顶点 i 的度 = 第 i 行(或列)非零元素个数
- 有向图出度 OD(i) = 第 i 行非零元素个数
- 有向图入度 ID(i) = 第 i 列非零元素个数
| 操作 | 时间复杂度 |
|---|---|
| 判断边是否存在 | O(1) |
| 求某顶点的度 | O(V) |
| 求所有边数 | O(V2) |
| 插删一条边 | O(1) |
| 插删一个顶点 | O(V2) |
重要性质:A^n[i][j] 表示顶点 i 到 j 长度为 n 的路径条数。
邻接表
存储方式:长度为 V 的顶点数组 + 每条顶点对应一条边链表。
typedef struct ArcNode { int adjvex; struct ArcNode *next;} ArcNode;
typedef struct VNode { char data; ArcNode *first;} VNode, AdjList[MaxVertexNum];
typedef struct { AdjList vertices; int vexnum, arcnum;} ALGraph;| 操作 | 时间复杂度 |
|---|---|
| 建立邻接表 | O(V+E) |
| 求顶点出度 | O(度(Vi)) |
| 求顶点入度(有向图) | O(V+E) |
| BFS/DFS 遍历 | O(V+E) |
特点:
- 无向图边结点数为 2E,有向图边结点数为 E
- 邻接表的表示不唯一(链表结点顺序可变)
- 有向图的邻接表只能直接查出出度;如需高效求入度,应使用逆邻接表或十字链表
十字链表(有向图专用)
弧结点结构:| tailvex | headvex | hlink | tlink | info |
顶点结点结构:| data | firstin | firstout |
- 沿
firstout + tlink遍历所有出弧(求出度) - 沿
firstin + hlink遍历所有入弧(求入度) - 空间复杂度 O(V+E),与邻接表相同
邻接多重表(无向图专用)
边结点结构:| mark | ivex | ilink | jvex | jlink | info |
顶点结点结构:| data | firstedge |
- 每条边只用一个边结点表示,被两个顶点的链表共享
- 删除边只需删除一个结点(邻接表需删两个)
- mark 标志位用于标记边是否已被访问
四种存储结构对比
| 存储结构 | 适用图类型 | 空间复杂度 | 求度 | 判边 | 删边 |
|---|---|---|---|---|---|
| 邻接矩阵 | 有向/无向 | O(V2) | O(V) | O(1) | O(1) |
| 邻接表 | 有向/无向 | O(V+E) | 出度 O(度),入度 O(V+E) | O(V) | 需删两个结点(无向图) |
| 十字链表 | 有向图 | O(V+E) | 出度/入度均快速 | O(V) | O(V) |
| 邻接多重表 | 无向图 | O(V+E) | O(度数) | O(V) | 只需删一个结点 |
易错:十字链表只适用于有向图,邻接多重表只适用于无向图。邻接表中无向边在两个顶点的链表中各存一次(共两个结点),邻接多重表中每条边只存一个结点。
考研高频考点
- 握手定理:由度数求边数,或由边数求度数
- 连通图的最少/最多边数判断
- 连通分量与强连通分量的区分
- 完全图的边数公式
- 二部图的判定条件(不含奇数回路)
- 四种存储结构的适用场景和优缺点对比
- 邻接矩阵 vs 邻接表的时间复杂度对比:O(V2) vs O(V+E)
- 十字链表和邻接多重表的适用场景区分
关联页面
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!










