数据结构---图的定义和存储结构

图的定义和基本术语

图(Graph) G由两个集合V和E组成,记为G=(V,E) , 其中V是顶点的有穷非空集合,E是V中顶点偶对的有穷集合,这些顶点偶对称为边。其中点不能为空,边可以为空。

无向图中,顶点对(x,y)是无序的

有向图中,顶点对<x,y>是有序的

基本术语

用n表示图中顶点数目,用e表示边的数目

名称 概念
子图 假设有两个图 G = (V, E)和 G'= (V', E'), 如果V'属于V且 E'属于E, 则称 G'为 G 的子图
无向完全图 具有 n(n- 1)/2 条边,任意两个顶点都有边相连
有向完全图 具有n(n- 1)条弧,任意两个顶点都有有向边相连
权和网 每条边可以标上具有某种含义的数值,该数值称为该边上的权,带权的图通常称为网
邻接点 对于无向图 G, 如果图的边 (v, v')属于E, 则称顶点 v 和 v'互为邻接点, 即 v 和 v'相邻接。边 (v, v')依附于顶点 v 和 v', 或者说边 (v, v')与顶点 v 和 v'相关联
度、入度和出度 顶点的度是指和v相关联的边的数目,入度是以顶点v为头的弧的数目,出度是以顶点 v为尾的弧的数目,度=出度+入度=2*边
路径和路径长度 在无向图 G 中,从 顶点 v 到顶点 v'的 路径是一个顶点序列,路径长度是一条路径上经过的边或弧的数目
回路或环 第一个顶点和最后一个顶点相同的路径称为回路或环
简单路径、 简单回路或简单环 序列中顶点不重复出现的路径称为简单路径。除了第一个顶点和最后一个顶点之外,其余顶点不重复出现的回路,称为简单回路或简单环
连通、连通图和连通分量 在无向图 G 中,如果从顶点 v 到顶点 v'有路径,则称 v 和 v'是连通的;如果对于图中任意两个顶点都是连通的,则称 G 是连通图;连通分量, 指的是无向图中的极大连通子图
强连通图和强连通分量 在有向图 G中,如果对千每一对 Vi, Vj属于V,且两者不等 , 从 Vi到 Vj 和 从 Vj到Vi都存在路径,则称G是强连通图,有向图中的极大强连通子图称作有向图的强连通分量
连通图的生成树 一个极小连通子图,它含有图中全部顶点,但只有足以构成一棵树的 n-1条边,这样的连通子图称为连通图的生成树
有向树和生成森林 有一个顶点的入度为 0, 其余顶点的入度均为 l 的有向图称为有向树。 一个有向图的生成森林是由若干棵有向树组成,含有图中全部顶点,但只有足以构成若干棵不相交的有向树的弧。

图的类型定义

image-20220207165425943

image-20220207165517462

图的存储结构

由于图复杂的结构,顶点间都可能存在联系,所有没有顺序存储结构但可以借助二维数组来表示元素之间的关系,即邻接矩阵表示法

1.邻接矩阵表示法

若是图

image-20220207165937616

若是网

image-20220207170037783

用邻接矩阵表示时除了存储邻接矩阵的二维数组外还需一个一维数组存储顶点信息

image-20220207170456500

无向图的邻接矩阵

特点:

1.矩阵是对称矩阵

2.顶点i的度为第i行(列)中1的个数

若是完全图,对角元素全为0,其余元素为1

有向图的邻接矩阵

特点:

1.第i行为结点i的出度边,出度=第i行元素之和

2.第i列为结点i的入度边,入读=第i列元素之和

3.矩阵可能不是对称矩阵

4.顶点的度=第i行元素之和+第i列元素之和

图的邻接矩阵存储表示
#define Maxint 32767//表示极大值
#define MVNum 100 //最大顶点数
typedef char VerTexType;//设顶点的数据类型为字符型
typedef int ArcType;//设边的权值类型为整型
typedef struct
{ 
VerTexType vexs [MVNum] ; //一维数组来存放顶点
ArcType arcs[MVNum][MVNum]; //二维数组来存放邻接矩阵
int vexnum,arcnum; //图的点数和边数
}AMGraph;
创建无向网
Status CreateUDN(AMGraph &G) 
{
cin>>G.vexnum>>G.arcnum; //输入总顶点数,总边数
for(i=O;i<G.vexnum;++i) 
cin>>G.vexs[i]; //依次输入点的信息
for(i=O;i<G.vexnum;++)//初始化邻接矩阵,边的权值初始化为极大值
for (j =0; j <G. vexnum; ++j) 
G.arcs[i][j]=Maxint;
for(k=O;k<G.arcnum;++k) //构造邻接矩阵
{
cin>>vl>>v2>>w; //输入边依附的顶点和权值
i=LocateVex(G,vl);j=LocateVex(G,v2); //确定vl和v2在G中的位置,即顶点数组的下标
G.arcs[i] [j]=w; //边<vl, v2>的权值置为w
G.arcs[j] [i]=G.arcs[i] [j];//置<vl, v2>的对称边<v2, vl>的权值为w
}
 return OK;
}
int LocateVex(AMGraph G,VertexType u)
{
int i;
for(i=0;i<G.vexnum;++i)
if(u==G.vexs[i])return i;
return -1;
}

时间复杂度为O(n*n)

创建无向图

对上述算法做改动

一是初始化邻接矩阵时,将边的权值均初始化为0; 二是构造邻接矩阵时,将权值w改为常量值1

创建有向网

对上述算法做改动

删除G.arcs[j] [i]=G.arcs[i] [j];这一步,因为有向网不一定是对称的

创建有向图

和创建无向图一样1做改动并删除G.arcs[j] [i]=G.arcs[i] [j];这一步

邻接矩阵优缺点:

优点
  • 便于判断两个顶点之间是否有边
  • 便于计算各个顶点的度
缺点
  • 不便于增加和删除顶点
  • 不便于统计边的数目
  • 空间复杂度高。对于稀疏图而言尤其浪费空间

由于图的任意两个顶点间都可能存在关系,因此,用链式存储表示图是很自然的事,图的链式存储有多种,有邻接表、十字链表和邻接多重表

2.邻接表

在邻接表中,对图中每个顶点Vi 建立一个单链表,把与 Vi相邻接的顶点放在这个链表中,邻接表中每个单链表的第一个结点存放有关顶点的信息, 把这一结点看成链表的表头, 其余结点存放有关边的信息

image-20220207175445654

表头结点表:

顺序结构存储,数据域 (data) 存储顶点 Vi的名称或其他有关信息

链域 (firstarc) 指向链表中第一个结点(即与顶点 Vi邻接的第一个邻接点)

边表:

链式结构存储,邻接点域(adjvex)指示与顶点 Vi邻接的点在图中的位置

数据域 (info) 存储和边相关的信息, 如权值等

链域 (nextarc) 指示与顶点vi邻接的下一条边的结点

图的邻接表的存储表示
#define MVNum 100//最大顶点数
typedef struct ArcNode//边结点
{
int adjvex; //该边所指向的顶点的位置
struct ArcNode * nextarc; //指向下一条边的指针
Otherinfo info; //和边相关的信息
}ArcNode; 
typedef struct VNode //顶点
{
VerTexType data;//顶点信息
ArcNode *firstarc; //指向第一条依附该顶点的边的指针
}VNode,AdjList[MVNum]; //Adjust表示邻接表类型
typedef struct //邻接表
{
AdjList vertices; 
int vexnum,arcnum; //图的当前顶点数和边数
}ALGraph;
创建无向图
Status CreateUDG(ALGraph &G) 
{
cin>>G.vexnum>>G.arcnum;//输入总顶点数, 总边数
for(i=O;i<G.vexnum;++i)//输入各点,构造表头结点表
{
cin>>G.vertices[i] .data; //输入顶点值
G.vertices[i] .firstarc=NULL;//初始化表头结点的指针域为NULL
}
for(k=O;k<G.arcnum;++k) 
{
cin>>vl>>v2; //输入 一条边依附的两个顶点
i=LocateVex(G,vl); j =LocateVex(G,v2); //确定vl和 v2在G中位置, 即顶点在G.vertices中的序号
pl=new ArcNode; //生成一个新的边结点*pl
pl->adjvex=j; //邻接点序号为j
pl->nextarc=G.vertices[i].firstarc; G.vertices [i].firstarc= pl; //将新结点*pl插入顶点Vi的边表头部
p2=new ArcNode; //生成一个新的边结点*p2
p2->adjvex=i; //邻接点序号为i
p2->nextarc=G.vertices[j] .firstarc; G.vertices[j] .firstarc=p2; //将新结点*p2插入顶点Vj的边表头部
} 
return OK;
}

时间复杂度O(n+e)

创建有向图

每读入一个顶点对序号<i,j>仅需生成一个邻接点序号为的边表结点, 并将其插入到 Vi的边链表头部

即对上述算法删除构造p2后的操作

创建有向/无向网

在边结点的info域中存储权值

邻接表表示法的优缺点

优点:
  • 便于增加和删除顶点
  • 便于统计边的数目
  • 空间效率高,适合表示稀疏图
缺点:
  • 不便于判断顶点之间是否有边
  • 不便于计算有向图各个顶点的度,求出度容易,求入度难

求入度可以利用逆邻接表

邻接矩阵和邻接表表示法的关系
区别:
  1. 对于任一确定的无向图,邻接矩阵的唯一的,邻接表不唯一(边结点的顺序不定)
  2. 邻接矩阵的空间复杂度O(n*n)多用于稠密图,邻接表的空间复杂度O(n+e)多用于稀疏图

为了解决邻接表表示法构建有向图求结点的度困难,引入十字链表

3.十字链表

可以看成将有向图的邻接表和逆邻接表结合起来得到的一种链表

image-20220207192836609

image-20220207193256585

尾域 (tailvex) 和头域 (headvex) 分别指示弧尾和弧头这两个顶点在图中的位置

链域 hlink 指向弧头相同的下一条弧

链域 tlink 指向弧尾相同的下一条弧

info域指向该弧的相关信息

data 域存储和顶点相关的信息,如顶点的名称等

firstin 和 firstout为两个链域,分别指向以该顶点为弧头或弧尾的第一个弧结点

这样就实现了弧头相同的弧在同一链表上,弧尾相同的弧也在同一链表上

十字链表的存储表示
#define MAX_ VERTEX_NUM 20 
typedef strut ArcBox //弧结点
{
int tailvext,headvex;//该弧的尾和头顶点的位置
struct ArcBox *hlink, *tlink;//分别为弧头相同和弧尾相同的弧的链域
InfoType *info;//该弧相关信息的指针
}ArcBox; 
typedef struct VexNode //顶点结点
{
VertexType data; 
ArcBox *firstin,*firstout; //分别指向该顶点第一条人弧和出弧
}VexNode; 
typedef struct //图
{
VexNode xlist [MAX_VERTEX_NUM]; //表头向扯
int vexnnm, arcnum; //有向图的当前顶点数和弧数
}OLGraph;

为了解决邻接表表示法构建无向图每条边都要存储两遍的缺点,引入邻接多重表

4.邻接多重表

image-20220207194424987

mark 为标志域,可用以标记该条边是否被搜索过

ivex 和 jvex为该边依附的两个顶点在图中的位置

ilink 指向下一条依附于顶点 ivex 的边

jlink 指向下一条依附千顶点jvex的边

info为指向和边相关的各种信息的指针域

data域存储和该顶点相关的信息

firstedge域指示第一条依附于该顶点的边

这样就使得所有依附千同一顶点的边串联在同一链表中,由于每条边依附于两个顶点,则每个边结点同时链接在两个链表中

邻接多重表存储表示
#define MAX_VERTEX_NUM 20
typedef enum{unvisited,visited} Visitlf;
typedef struct EBox边结点
{
Visitlf mark;//访问标记
int ivex, jvex;//该边依附的两个顶点的位置
struct EBox *ilink, *jlink; //分别指向依附这两个顶点的下一条边
InfoType *info; //该边信息指针
} Ebox; 
typedef struct VexBox //顶点结点
{ 
VertexType data; 
EBox *firstedge;//指向第一条依附该顶点的边
}VexBox; 
typedef struct//无向图
{ 
VexBox adjmulist [MAX_VERTEX_NUM]; 
int vexnum, edgenum; //无向图的当前顶点数和边数
}AMLGraph;

posted on   眉目作山河  阅读(658)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示