![![[Pasted image 20250926104415.png]]](https://i-blog.csdnimg.cn/direct/57b90f8352834488a9061e78d227da36.png)
图的基本概念
图的定义
图(Graph) G 由两个集合和 E 组成, 记为 G=(V,E), 其中 V 是顶点的有穷非空集合, E 是顶点中偶对的有穷集合, 这些顶点偶对称为边。
V(G)和 E(G)通常分别表示图 G 的顶点集合和边集合, E(G)可以为空集。若 E(G)为空, 则图 G 只有顶点而没有边。
|V| 表示图顶点数, 也称为图的阶; |E|表示图的边数。 |V|>=1, |E|>=0,
即图可以只有一个点, 也可以一条边也没有, 就是不能一个点也没有, 这与之前的线性表和树完全不一样的。
图的分类
![![[Pasted image 20251001033409.png]]](https://i-blog.csdnimg.cn/direct/04a16a15c043436cbcae51a813d5e156.png)
-
有向图
构成一个图的边集为有向边, 每条边(弧)都有方向。
如: 顶点对<A,C>是有序的, 表示从A到C的一条弧,A为弧尾,C为弧头。<A,C>与<C,A>是不同的两条弧。 -
无向图
构成图的边集是无向边, 每条边都没有方向。 如: 顶点对(A,C)是无序的, (A,C)与(C,A)是同一条边,A,C互为邻接点。 -
简单图
图中不存在某顶点到自身的边, 且不存在重复的边, 则成为简单图。 -
多重图
顶点有直接与自身相连的边(自环) , 或无向图中任意两个顶点之间存在多对平行边。 -
稠密图、 稀疏图
根据边的数目进行界定, 一般图 G 满足∣E∣<∣V∣∗log∣V∣|E|<|V|*log|V|∣E∣<∣V∣∗log∣V∣, 可以将图G看为稀疏图
![![[Pasted image 20251001033839.png]]](https://i-blog.csdnimg.cn/direct/ef98a92331fe4d0e93c86f998e4db4aa.png)
-
无向完全图
由 n 个顶点组成的无向图中, 任意两顶点之间都存在边, 共由 n(n−1)2\frac{n(n-1)}{2}2n(n−1) 条边。 -
有向完全图
由 n 个顶点组成的有向图中, 任意两顶点之间存在反向相反的两条边, 共有 n(n−1)n(n-1)n(n−1)条边。
![![[Pasted image 20251001034002.png]]](https://i-blog.csdnimg.cn/direct/5327a644c0174809b8373e222e734ff4.png)
-
顶点的度
顶点的度: 图中以该顶点为一个端点的边的数目
无向图中: 顶点 v 的度是指依附于该顶点的边的条数, 记为 TD(v)。 具有 n 个顶点, e 条边的无向图中, 所有顶点的度总和是边数的二倍, 即
∑i=1nTD(vi)=2e \sum^{n}_{i=1}TD(v_{i}) = 2e i=1∑nTD(vi)=2e
有向图中: 顶点 v 的度分为入度和出度。 入度是以顶点 v 为终点的有向边的条数记为 ID(v); 出度是以顶点 v 为起点的有向边的数目, 记为OD(v)。 具有 n 个顶点, e 条边的有向图中, 全部顶点的入度之和与出度之和相等, 等于边数。 即
∑i=1nID(vi)=∑i=1nOD(vi)=e \sum^{n}_{i=1}ID(v_{i}) = \sum^{n}_{i=1}OD(v_{i}) = e i=1∑nID(vi)=i=1∑nOD(vi)=e -
路径
在图中, 顶点 VpV_{p}Vp 到顶点 VqV_{q}Vq 之间的顶点序列 Vp,Va,Vb…VqV_{p},V_{a},V_{b}…V_{q}Vp,Va,Vb…Vq。 -
路径长度
路径上边的数目, 若该路径最短则称之为距离。 -
简单路径
序列中顶点不重复出现的路径。
= 回路(环)
第一个顶点和最后一个顶点相同的路径。
注意: 若所给无向图有 n 个顶点, 并且有大于 n-1 条边, 则此图一定有环。
= 权
图中边具有与之相关的数值, 称之为权重, 权重可以表示从一个顶点到另一个 顶点的距离、 花费的代价等, 这种带权图也叫做网络。 -
图的连通性
- 子图
有两个图 G=(V,E)和 G’ =(V’ ,E’ ), 若 V‘是 V 的子集, 且 E’ 是 E 的子集, 则称 G‘为 G 的子图。 特别的, 当 G’ 的顶点集与 G 的顶点集相等, 则称 G’ 为 G 的生成子图。
- 子图
-
连通、 连通图、 连通分量
无向图中, 若从顶点 v 到顶点 w 有路径存在, 则称 v 和 w 是连通的。
若无向图中任意两个顶点都是连通的, 则称此无向图为连通图。
注意: 如果一个图有 n 个顶点和小于 n-1 条边, 则必然是非连通图。
连通分量: 无向图中的极大连通子图, 极大: 要求包含该连通子图的所有边。
![![[Pasted image 20251001044226.png]]](https://i-blog.csdnimg.cn/direct/5eafff4e4d9a4aa18b515b7bc54668b1.png)
-
强连通、 强连通图、 强连通分量
强连通: 有向图中, 若从顶点 v 到顶点 w 和顶点 w 到顶点 v 之间都有路径, 则称 v 和 w 是强连通的。
强连通图: 有向图 G 中任意两个顶点都是强连通的, 则此图为强连通图。
强连通分量: 有向图中的极大强连通子图。
![![[Pasted image 20251001044301.png]]](https://i-blog.csdnimg.cn/direct/994546adf5cb459985f1a33e344796df.png)
-
图与树、 森林的关系
连通图可以转为树, 非连通图可以转化为森林。
生成树: 连通图的生成树是包含图中全部顶点的一个极小连通子图。 若图中的顶点数为 n, 则它的生成树有 n-1 条边, 生成树不一定唯一。 对生成树而言, 若砍去它的一条边, 则会变成非连通图, 若加上一条边则会形成一个回路
生成森林: 非连通图中, 连通分量的生成树构成了非连通图的生成森林。
![![[Pasted image 20251001044339.png]]](https://i-blog.csdnimg.cn/direct/422f9563b9cd4375a117d208e51d4898.png)
![![[Pasted image 20251001044346.png]]](https://i-blog.csdnimg.cn/direct/51b352704117433c8b165941bd1bf61c.png)
图的储存结构
对于图 G=(V, E)来说, 可以有两种标准的表示方法, 一个是邻接矩阵,另一个是邻接表, 这两种方法都可以表示有向图和无向图。 除此之外, 图的存储结构还有十字链表、 邻接多重表。
邻接矩阵
图的邻接矩阵的存储方式是用两个数组来表示图。 即用一个一维数组存储图中顶点信息, 用一个二维数组存储图中边的信息(即各顶点间的邻接关系) , 存储顶点间邻接 关系的二维数组称为邻接矩阵。
设图 G=(V,E)包含 n 个顶点, 图顶点编号为 V1,V2,V3…VnV_{1},V_{2},V_{3} …V_{n}V1,V2,V3…Vn , 图 G 的邻接矩阵是一个二维数组 A[n][n],, 其定义为:
A[i][j]={1,若(vi,vj或<vi,vj>是E(G)的边)0,若(vi,vj或<vi,vj>不是E(G)的边)
A[i][j] = \left\{\begin{matrix}
1, \qquad 若(v_{i},v_{j}或<v_{i},v_{j}>是E(G)的边) \\
0, \qquad 若(v_{i},v_{j}或<v_{i},v_{j}>不是E(G)的边)
\end{matrix}\right.
A[i][j]={1,若(vi,vj或<vi,vj>是E(G)的边)0,若(vi,vj或<vi,vj>不是E(G)的边)
![![[Pasted image 20251001055333.png]]](https://i-blog.csdnimg.cn/direct/54bf9ef18a3a442b8062925333fda84c.png)
#define MAX_VERTEX_NUM 100 //最大顶点个数
typedef char VertexType; //顶点数据类型
typedef int EgdeType; //带权图边权值数据类型
typedef struct{
VertexType Vex[MAXVERTEXNUM]; //顶点表
EgdeType Edge[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //邻接矩阵,边表
int vexnum,arcnum; //图的当前顶点数,弧数
}Mgraph;
邻接矩阵法的空间复杂度为 O(n2), 适用于边稠密图。
注: 这里主要是为了和邻接表法所使用的存储空间做对比, 所以使用了”空间复杂度” 这个名词, 在实际的算法题中, 存储图所使用的空间并不会算入整个算法的空间复杂度。
-
无向图的邻接矩阵法
![![[Pasted image 20251001055906.png]]](https://i-blog.csdnimg.cn/direct/dc122ac2c28d45688ec8343839264435.png)
-
有向图的邻接矩阵法
![![[Pasted image 20251001055922.png]]](https://i-blog.csdnimg.cn/direct/2927c661bc674ad5886198e918e210c4.png)
-
带权图的邻接矩阵法
A[i][j]={wij,若(vi,vj或<vi,vj>是E(G)的边)0或∞,若(vi,vj或<vi,vj>不是E(G)的边) A[i][j] = \left\{\begin{matrix} w_{ij}, \qquad 若(v_{i},v_{j}或<v_{i},v_{j}>是E(G)的边) \\ 0或\infty, \qquad 若(v_{i},v_{j}或<v_{i},v_{j}>不是E(G)的边) \end{matrix}\right. A[i][j]={wij,若(vi,vj或<vi,vj>是E(G)的边)0或∞,若(vi,vj或<vi,vj>不是E(G)的边)
![![[Pasted image 20251001060107.png]]](https://i-blog.csdnimg.cn/direct/3bdcc47bd19b440db32b8130a251609d.png)
-
扩展知识
设图 G 的邻接矩阵为 A, An的元素 An[i][j]等于由顶点 i 到顶点 j 的长度为 n 的路径的数目。
![![[Pasted image 20251001060220.png]]](https://i-blog.csdnimg.cn/direct/0c0a468edbf6475ab2fbd5333d0daf43.png)
- 无向图的邻接矩阵一定是对称矩阵,常采用压缩存储;
- 对于无向图,邻接矩阵的第i行/列非零元素的个数对应顶点i的度;
- 对于有向图,邻接矩阵的第i行非零元素的个数对应顶点i的出度,第i列的非零元素对应顶点i的入度
- 采用邻接矩阵存储的图,易于确定图中任意顶点之间是否有边。但是难于计算边的总数;
- 稀疏图不建议使用邻接矩阵的方式存储。
邻接表法
邻接矩阵法, 空间复杂度为 O(n2), 存储稀疏图会存在空间浪费。
邻接表法是图的链式存储结构, 对图中的每个顶点建立一个单链表,第 i 个单链表中的结点表示依附于顶点 Vi的边(有向图则为以顶点 Vi 为尾的弧)。
邻接表中存在两种结点: 顶点表结点和边表结点。
顶点表: 采用顺序存储, 存储顶点的数据信息和边表的头指针。
边表: 采用链式存储, 存储邻接点域和指向下一条邻接边的指针域。
边表结点:
#define Max_Vertex_Num 100
// 图中顶点数目的最大值
typedef struct ArcNode{
//边表结点
int adjvex;
// 该弧所指向的顶点的位置
struct ArcNode *next;
//指向下一条弧的指针
}ArcNode;
顶点表结点:
typedef struct Vnode{
//顶点表结点
VertexType data;
// 顶点信息
ArcNode *first;
//指向第一条依附于该顶点的弧的指针
}Vnode,AdjList[Max Vertex Num];
邻接表:
typedef struct {
AdjList vertices;
// 邻接表
int vexnum,arcnum;
//图的顶点数和弧数
}ALGraph;
// ALGraph是以邻接表存储的图
![![[Pasted image 20251001061137.png]]](https://i-blog.csdnimg.cn/direct/7d651a27c2234f89a20baf0a43170fb0.png)
-
无向图的邻接表法
![![[Pasted image 20251001061157.png]]](https://i-blog.csdnimg.cn/direct/77383bd352fb4470b84488bd9255775f.png)
-
有向图的邻接表法
![![[Pasted image 20251001061222.png]]](https://i-blog.csdnimg.cn/direct/6738417e90824e7480570cc57c43b017.png)
- 无向图的邻接表存储需要0(|V|+2|E|)的空间,而有向图为0(|V|+|E|);
- 邻接表存储易于知道某个顶点的所有邻边,而不方便查找某两个顶点之间是否存在边;
- 对于邻接表存储的有向图,易于计算某个顶点的出度,而难于计算入度;
- 稀疏图建议使用邻接表的方式存储。
邻接多重表
无向图的一种链式存储结构, 由顶点表结点和边表结点组成。
顶点表结点: 存储顶点的数据信息和指示第一条依附于该顶点的边。
边表结点: 由六个域组成,
mark 标记域, 标记该边是否被搜索过,
ivex 和 jvex 为该边依附的两个顶点在图中的位置,
ilink 指向下一条依附于顶点 ivex 的边,
jlink 指向下一条依附于顶点 jvex 的边,
info 为指向和边相关的信息的指针域。
![![[Pasted image 20251001061436.png]]](https://i-blog.csdnimg.cn/direct/d3f36360c691434f85784837de7f53b7.png)
- 无向图的邻接多重表
![![[Pasted image 20251001061512.png]]](https://i-blog.csdnimg.cn/direct/1c9fd83059b24800b9ebee04f00304bd.png)
相比于邻接表, 邻接多重表对边进行删除操作时效率更高
十字链表
有向图的一种链式存储结构, 由顶点表结点和弧结点组成。
- 顶点表结点: 由三个域组成,
data 域存放顶点相关信息,
firstin 和 firstout 两个域 分别指向以该顶点为弧头或弧尾的第一个弧结点。 - 弧结点: 由五个域组成,
尾域(tailvex) 和头域(headvex) 分别指示弧尾和弧头 这两个顶点在图中的位置,
链域 hlink 指向弧头相同的下一条弧,
链域(tlink) 指向弧尾相同的下一条弧,
info 域指向该弧的相关信息。
![![[Pasted image 20251001061811.png]]](https://i-blog.csdnimg.cn/direct/9d505dc074614ceeae3156982a766f39.png)
在十字链表中, 容易求得各顶点的出度和入度
十字链表表示不唯一
图的基本操作
- Adjacent(G,x,y)判断图 G 是否存在边<x,y>或(x,y) 。
- Neighbors(G,x)列出图 G 中与结点 x 邻接的边。
- InsertVertex(G,x)在图 G 中插入顶点 x。
- DeleteVertex(G,x)从图中删除顶点 x。
- AddEdge(G,x,y)若无向边(x,y) 或者有向边<x,y>不存在, 则向图 G 中添加该边。
- RemoveEdge(G,x,y)若无向边(x,y)或者有向边<x,y>存在, 则在图 G 中删除该边。
- FirstNeighbor(G,x), 求图 G 中顶点 x 的第一个邻接点。
- Get_edge_value(G,x,y)获取图 G 中边(x,y) 或<x,y>对应的权值 v。
- Set_edge_value(G,x,y)设置图 G 中边(x,y) 或<x,y>对应的权值 v。
1056

被折叠的 条评论
为什么被折叠?



