NO.8数据结构图|定义|分类|邻接矩阵|邻接表|邻接多重表|十字链表

![[Pasted image 20250926104415.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]]

  • 有向图
    构成一个图的边集为有向边, 每条边(弧)都有方向。
    如: 顶点对<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<VlogV, 可以将图G看为稀疏图
    ![[Pasted image 20251001033839.png]]

  • 无向完全图
    由 n 个顶点组成的无向图中, 任意两顶点之间都存在边, 共由 n(n−1)2\frac{n(n-1)}{2}2n(n1) 条边。

  • 有向完全图
    由 n 个顶点组成的有向图中, 任意两顶点之间存在反向相反的两条边, 共有 n(n−1)n(n-1)n(n1)条边。
    ![[Pasted image 20251001034002.png]]

  • 顶点的度
    顶点的度: 图中以该顶点为一个端点的边的数目
    无向图中: 顶点 v 的度是指依附于该顶点的边的条数, 记为 TD(v)。 具有 n 个顶点, e 条边的无向图中, 所有顶点的度总和是边数的二倍, 即
    ∑i=1nTD(vi)=2e \sum^{n}_{i=1}TD(v_{i}) = 2e i=1nTD(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=1nID(vi)=i=1nOD(vi)=e

  • 路径
    在图中, 顶点 VpV_{p}Vp 到顶点 VqV_{q}Vq 之间的顶点序列 Vp,Va,Vb…VqV_{p},V_{a},V_{b}…V_{q}Vp,Va,VbVq

  • 路径长度
    路径上边的数目, 若该路径最短则称之为距离。

  • 简单路径
    序列中顶点不重复出现的路径。
    = 回路(环)
    第一个顶点和最后一个顶点相同的路径。
    注意: 若所给无向图有 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]]

  • 强连通、 强连通图、 强连通分量
    强连通: 有向图中, 若从顶点 v 到顶点 w 和顶点 w 到顶点 v 之间都有路径, 则称 v 和 w 是强连通的。
    强连通图: 有向图 G 中任意两个顶点都是强连通的, 则此图为强连通图。
    强连通分量: 有向图中的极大强连通子图。
    ![[Pasted image 20251001044301.png]]

  • 图与树、 森林的关系
    连通图可以转为树, 非连通图可以转化为森林。
    生成树: 连通图的生成树是包含图中全部顶点的一个极小连通子图。 若图中的顶点数为 n, 则它的生成树有 n-1 条边, 生成树不一定唯一。 对生成树而言, 若砍去它的一条边, 则会变成非连通图, 若加上一条边则会形成一个回路
    生成森林: 非连通图中, 连通分量的生成树构成了非连通图的生成森林。
    ![[Pasted image 20251001044339.png]]

![[Pasted image 20251001044346.png]]

图的储存结构

对于图 G=(V, E)来说, 可以有两种标准的表示方法, 一个是邻接矩阵,另一个是邻接表, 这两种方法都可以表示有向图和无向图。 除此之外, 图的存储结构还有十字链表、 邻接多重表。

邻接矩阵

图的邻接矩阵的存储方式是用两个数组来表示图。 即用一个一维数组存储图中顶点信息, 用一个二维数组存储图中边的信息(即各顶点间的邻接关系) , 存储顶点间邻接 关系的二维数组称为邻接矩阵。
设图 G=(V,E)包含 n 个顶点, 图顶点编号为 V1,V2,V3…VnV_{1},V_{2},V_{3} …V_{n}V1,V2,V3Vn , 图 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]]

#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]]

  • 有向图的邻接矩阵法
    ![[Pasted image 20251001055922.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]]

  • 扩展知识
    设图 G 的邻接矩阵为 A, An的元素 An[i][j]等于由顶点 i 到顶点 j 的长度为 n 的路径的数目。
    ![[Pasted image 20251001060220.png]]

  1. 无向图的邻接矩阵一定是对称矩阵,常采用压缩存储;
  2. 对于无向图,邻接矩阵的第i行/列非零元素的个数对应顶点i的度;
  3. 对于有向图,邻接矩阵的第i行非零元素的个数对应顶点i的出度,第i列的非零元素对应顶点i的入度
  4. 采用邻接矩阵存储的图,易于确定图中任意顶点之间是否有边。但是难于计算边的总数;
  5. 稀疏图不建议使用邻接矩阵的方式存储。
邻接表法

邻接矩阵法, 空间复杂度为 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]]

  • 无向图的邻接表法
    ![[Pasted image 20251001061157.png]]

  • 有向图的邻接表法
    ![[Pasted image 20251001061222.png]]

  1. 无向图的邻接表存储需要0(|V|+2|E|)的空间,而有向图为0(|V|+|E|);
  2. 邻接表存储易于知道某个顶点的所有邻边,而不方便查找某两个顶点之间是否存在边;
  3. 对于邻接表存储的有向图,易于计算某个顶点的出度,而难于计算入度;
  4. 稀疏图建议使用邻接表的方式存储。
邻接多重表

无向图的一种链式存储结构, 由顶点表结点和边表结点组成。
顶点表结点: 存储顶点的数据信息和指示第一条依附于该顶点的边。
边表结点: 由六个域组成,
mark 标记域, 标记该边是否被搜索过,
ivex 和 jvex 为该边依附的两个顶点在图中的位置,
ilink 指向下一条依附于顶点 ivex 的边,
jlink 指向下一条依附于顶点 jvex 的边,
info 为指向和边相关的信息的指针域。
![[Pasted image 20251001061436.png]]

  • 无向图的邻接多重表
    ![[Pasted image 20251001061512.png]]

相比于邻接表, 邻接多重表对边进行删除操作时效率更高

十字链表

有向图的一种链式存储结构, 由顶点表结点和弧结点组成。

  1. 顶点表结点: 由三个域组成,
    data 域存放顶点相关信息,
    firstin 和 firstout 两个域 分别指向以该顶点为弧头或弧尾的第一个弧结点。
  2. 弧结点: 由五个域组成,
    尾域(tailvex) 和头域(headvex) 分别指示弧尾和弧头 这两个顶点在图中的位置,
    链域 hlink 指向弧头相同的下一条弧,
    链域(tlink) 指向弧尾相同的下一条弧,
    info 域指向该弧的相关信息。
    ![[Pasted image 20251001061811.png]]

在十字链表中, 容易求得各顶点的出度和入度
十字链表表示不唯一

图的基本操作
  1. Adjacent(G,x,y)判断图 G 是否存在边<x,y>或(x,y) 。
  2. Neighbors(G,x)列出图 G 中与结点 x 邻接的边。
  3. InsertVertex(G,x)在图 G 中插入顶点 x。
  4. DeleteVertex(G,x)从图中删除顶点 x。
  5. AddEdge(G,x,y)若无向边(x,y) 或者有向边<x,y>不存在, 则向图 G 中添加该边。
  6. RemoveEdge(G,x,y)若无向边(x,y)或者有向边<x,y>存在, 则在图 G 中删除该边。
  7. FirstNeighbor(G,x), 求图 G 中顶点 x 的第一个邻接点。
  8. Get_edge_value(G,x,y)获取图 G 中边(x,y) 或<x,y>对应的权值 v。
  9. Set_edge_value(G,x,y)设置图 G 中边(x,y) 或<x,y>对应的权值 v。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值