假设以邻接矩阵作为图的存储结构_学习数据结构--第五章:图(图的存储方法)

第五章:图(图的存储方法)

1.邻接矩阵法

下面是一个无向图的表示,我们使用一个一维数组存放点集,使用一个二维数组存放边集

41100cf60d3679a0b7645c5e097bceac.png

二维数组表示边:行号表示其实端点,列号表示结束端点,值表示该边是否存在,以及该边的权重,我们称这种二维数组表示的矩阵为邻接矩阵

邻接矩阵法:- 结点数为n的图G=(V,E)的邻接矩阵A是n*n的(每个行号表示一个结点每个列号表示一个结点,n个结点即为n*n)- 将G的顶点编号为 V1,V2,V3......Vn (1,2,3.....数组下标)- 若 存在,则A[i][j]=1,否则A[i][j]=0
f3999505270fd085835d27fc717a6784.png

注意有向边和无向边是不一样的,有向边 Vi---->Vj,则存放A[i][j]=1,若无向边Vi-------Vj,则存放A[i][j]=1、A[j][i]=1 .

有向图邻接矩阵:

3756210217c18a6d93bc89099619f08d.png

无向图邻接矩阵:(关于对角线对称)

8c84a08c193b97c8b8ee12b897bd2048.png

有权重的图:

f0e622b8b1220efd6e5b0579c3a68d18.png

有向边 Vi---->Vj,则存放A[i][j]=Wi,j,若无向边Vi-------Vj,则存放A[i][j]=Wi,j、A[j][i]=Wi,j .

网转邻接矩阵

1606c0761781bb4a3f00efc5cc7f6df5.png

语言实现

#define MaxvertexNum 100 typedef char VertexType; //每个结点时字符型的(类型可自行调整)typedef int EdgeType; //可表示便是否存在、边的权重(类型可以自行调整)typedef struct{      VertexType Vex[MaxVertexNum];//点集数组     EdgeType Edge[MaxVertexNum][MaxVertexNum];//边集数组     int vexnum,arcnum;//结点的数量和边的数量}MGraph;

邻接矩阵法的空间复杂度位O(n^2)

2.邻接矩阵性质

aca6c5952d221ba452e65fb66fcdefcc.png

性质1:邻接矩阵法的空间复杂度为O(n^2),适用于稠密图

因为无论该边是否存在,我们都会为其申请空间,所以稠密图也就是边越多的图它的空间利用率也就越高

性质2:无向图的邻接矩阵为对称矩阵

性质3:无向图中第 i 行(或第 i 列)非0元素(非正无穷)的个数为第 i 个顶点的度;有向图中第 i 行(第 i 例)非0元素(非正无穷)的个数为第 i 个顶点的出度(入度)

设图G的邻接矩阵为A,矩阵运算A^n的含义??

我们先看A^2,首先两个矩阵,我们知道A^2[2][5]=1*1+0*0+1*1+0*0+0*0=2

5257cf2eaf071e2717ad0cff7a3d678a.png

首先第一个1*1:第一个1代表B->A,第二个1代表A->E,相乘代表B->E存在一条B->A->E的路径,第二个1*1:第一个1代表B->C,第二个1代表C->E,相乘代表B->E存在一条:B->C->E的路径。

所以:A^2[2][5]=2表示从顶点V2(B)到顶点V5(E)长度为2的路径有两条。(长度为2因为是的A方,两条是因为值为2)

现在我们再看A^3,首先两个矩阵,一个是A^2,一个是A

78bb28a784521212004267b874d5e566.png

则:A^3[2][5]=0*0+0*0+1*1+1*0+2*0=1,首先我们知道A^2[2][3]=1表示从顶点V2->V5长度为2的路径只有一条,则A^3[2][5]=1表示从顶点V2到顶 点V5长度为3的路径只有一条

综上我们可知A^n[i][j]表示从顶点vi到顶点Vj长度为n的路径的条数

2.邻接矩阵表

2243bacfb6a8562b3c05c30faa1f2eb8.png

上面讲解了邻接矩阵法,对于上面的稀疏图,我们如果采用邻接矩阵法存储的话,会出现很多空间的浪费即

邻接矩阵法存储稀疏图会有许多空间浪费 ,对于稀疏图我们通常采用邻接表法存储

邻接表法:为每一个顶点建立一个单链表存放与它相邻的边- 顶点表:采用顺序存储,每个数组元素存放顶点的数据和边表的头指针- 边表(出边表):采用链式存储,单链表中存放与一个顶点相邻的所有边,一个链表结点表示一条从该顶点到链表结点顶点的边

c42a43439cff6223e3af5fad1b6b795b.png

3.邻接表法

有向图:

577f4715461e36e48ea221aa3417876d.png

无向图:

5b086cdcc84919e57bb056e3cbcc34fd.png

代码实现

#define MaxVertexNum 100 //边表typedef struct ArcNode{     int adjvex; //下一个结点的下标    struct ArcNode *next;//指针指向下一个边表结点    //InfoType info; //表的权重}ArcNode;//顶点表typedef struct VNode{     VertexType data;//数据    ArcNode *first //指向属于它的边表的头指针}VNOode,AdjList [MaxVertexNum];//数组类型//邻接表typedef struct{     AdjList vetices;//顶点表    int vexnum,arcnum;//顶点数量和边的数量}ALGraph;

表特点

V表示顶点数量、E表示边的数量

  • 若G为无向图,存储空间为O(V+2E)
  • 若G为有向图,存储空间为O(V+E)
  • 邻接表更加适用于稀疏图
  • 若G为无向图,则结点的度为该结点边表的长度
  • 若G为有向图,则结点的出度为该结点边表的长度,计算入度则要遍历整个邻接表
  • 邻接表不唯一,边表结点的顺序根据算法和输入的不同可以能会不同

4.邻接矩阵VS邻接表

4b21566983b8eea056eb5e2b5df79355.png

5.十字链表

·十字链表:有向图 的一种链式存储结构

我们在邻接表中可以发现,如果寻找一个结点的出度,非常方便,直接遍历该节点的边表即可,但是如果想找一个结点的入度则需要遍历整个邻接表比较复杂,所以我们引入了十字链表,它无论是查询结点的出度和入度都比较简单。

顶点表结点

data:数据域
firstin:入边单链表的头指针
firstout:出边单链表的头指针

边表结点

tailvex:该弧弧尾端点
headvex:该弧弧头端点
hlink:下一个弧弧头的指针
tlink:下一个弧弧尾的指针
info:边的权重

7d8d065fe6084220f044111264fc81d7.png

代码实现

#define MaxVertexNum 100 typedef struct ArcNode{        int tailvex,headvex;        struct ArcNode *hlink,*tlink;        //InfoType info: }ArcNode; typedef struct VNode{        VertexType data;        ArcNode *firstin,*firstout; }VNode;typedef struct{        VNode xlist[MaxVertexNum];       int vexnum, arcnum; }GLGraph;

6.邻接多重表

上面讲的·十字链表是 有向图 的一种链式存储结构,而邻接多重表则是针对无向图的一种链式存储结构。

4ab8ee79768d1fa417798655be8f9c11.png

我们在邻接表中如果想要删除一条无向边,我们需要找到对应的结点,然后遍历其边表,找到对应的边表结点并把它删除,这样操作的效率比较低。由此引出邻接多重表

ivex:该边的第一个端点ilink:与第一个端点相邻的下一个边的边表结点的指针jvex:该边的第二个端点jlink:与第二个端点相邻的下一个边的边表结点的指针info:权重(不必要)mark:标记(不必要)

feb63dc5ab62ab68f69b6f949eb64ad0.png
#define MaxVertexNum 100 typedef struct ArcNode{        int ivex, jvex;        struct ArcNode *ilink, *jlink;        //InfoType info;        //bool mark: }ArcNode;typedef struct VNode{        VertexType data;        ArcNode *firstedge; )VNode;typedef struct{        VNode adjmulist[MaxVertexNum];       int vexnum, arcnum; }AMLGraph;

7.理木客

数据结构相关知识,公众号理木客同步更新中,欢迎关注

5f95c5a67f86486fdeba43f378eaa05d.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值