考研之数据结构021_图的存储

PS:总结:主要理解每一个特性。

  • 考试常考是:【邻接矩阵】和【邻接表】

  • 十字链表法:只能存储有向图。
    解决:
    1、邻接矩阵空间复杂度高
    2、邻接表找入度比较麻烦需要遍历所有节点。

  • 邻接多重表:只能存储无向图
    解决了:
    1、邻接矩阵空间复杂度高
    2、邻接表中的删除边和顶点不方便问题。
    3、每个边对应两份冗余数据。

在这里插入图片描述

一、邻接矩阵(一维+二维数组)

  • 数组实现的顺序存储,空间复杂度高0(n2)【n是结点的个数】,适合稠密图、不适合稀疏图

在这里插入图片描述

无向图:
是没有方向的,每一条边对应两个1.
1:表示的是:两个顶点之间,相互邻接
0:表示的是:两个顶点之间,相互不邻接
在这里插入图片描述
有向图:
由于是有方向的:每一条边对应1个1
A指向B的弧或者边。A行B列是为1。但是B行A列可能没有。

在这里插入图片描述
代码的实现:对邻接矩阵的定义:
在这里插入图片描述

  • 如何求顶点的度、入度、出度?

无线图:
遍历所对应的某一行、列,记录非0元素的个数。得出度。
第i个结点的度=第i行(或第j列)的非零元素的个数。
时间复杂度是0(n),N是顶点的个数。也就是顶点V的个数。

有向图:
在这里插入图片描述

  • 邻接矩阵法存储带权图(网)
    在这里插入图片描述

-空间复杂度:0(n2) ——只和顶点数相关,和实际的边数无关。

  • 适合用于存储稠密图,也就是边很多的图。
    在这里插入图片描述

二、邻接表(顺序加链式)

在这里插入图片描述

1、常考的点:

邻接表:表示方式并不唯一。
比如A和bcd都相连。A的边链表可以用(123,也可以321的顺序)

邻接矩阵:
只要确定了各个结点的编号。图的邻接矩阵表示方式是唯一的。

在这里插入图片描述

2、代码分析:

1.顶点信息

  • 用一维数组来存储顶点结点的信息,其中包括:数据域data、指向顶点的第一条边/弧的指针。
    在这里插入图片描述

2.声明图

  • 声明图:
  • 1.顶点结点的一个数组
  • 2.记录当前具体有多少个结点、边
    在这里插入图片描述

3.边、弧的定义

//当前的边指向的那个结点。比如说:如果B的数组索引为1。A—>B.那么A指向的就是1。
在这里插入图片描述

3、邻接表存储有向图

例如A—>B。 那么A的后面跟了一个结点是1的弧。
结点存储的值是,是从该节点出发,到达该结点的索引。

在这里插入图片描述

1.求顶点的度=入度+出度

遍历这个结点 边界点的链表。从当前链表出去的的弧,也就是出度 。
而找到入度很麻烦:把所有节点的边链表都遍历

4、邻接表存储无向图

在这里插入图片描述

每一条边:在邻接表中都会对应两个结点。(a,b)(b,a)是一条边,但是表示了两次。所以边的数据是有冗余的。

  • 边的结点的数量是边的实际数量的2倍。
    在这里插入图片描述

1.求顶点的度

遍历这个顶点相关的单链表,有多少个边链表就是有多少个度。

三、十字链表(只能存储有向图)

一、邻接矩阵、邻接表的分析:

邻接矩阵的问题是:空间复杂度太高是:0(v2)。
邻接表的问题是:存储有向图的时候,要找入度不方便,需要遍历整个表。
而用十字链表来存储有向图的话,就可解决入度不方便和空间复杂度。

二、定义两个结构体:

顶点结点:
fistout指针:一直往后找各个结点,就可以找到从当前的顶点出发的所有的弧
fistin指针:一直顺着fistin指针,就可以找到所有指向当前结点的弧。
在这里插入图片描述
弧结点:

在这里插入图片描述

-共有四个结点ABCD,结点的信息存放在数组中。索引为0123
-A指向B和C。
A结点的firstout指针指向第一条弧的信息,也就是A指向B。
那么顺着它指向的tlink指针指向的是:弧尾相同的下一条弧。
也就是A指向的C。 
-还有两条弧指向的是A:D和C指向A
-那么需要顺着A结点指向的fistin指针。也就是说C指向A。
继续顺着hlink指针,找到fistiin指针下一条弧。D指向A。
那么下面hlink指针为空,说明没有其他节点指向A的弧了

在这里插入图片描述

三、十字链表有向图空间复杂度:0(v+e)

在这里插入图片描述

四、邻接多重表(只能存储无向图)

一、分析邻接表:

用邻接表存储的问题:
1.每一条边会存储两次。每条边对应两份冗余信息。比如A和B有一条边,存储的时候就会A指向B,B指向A。
2.删除顶点:删除了A结点,还有删除A结点的边。还需要找到,冗余数据,将边界点指向A结点的存储进行删除。

二、邻接多重表的分析:

用邻接多重表来存储无向图:
想要找到和某结点相连接的边很方便。并且:每一条边只会对应一个边结点。只有一份数据。
这种特性就可以保证当我们删除边,很方便。

一、定义两个结构体:

1.顶点结点:
数据域和指针是指向 和当前这个顶点相连接的第一条边。
在这里插入图片描述

2.边界点
iLink:依附于顶点i的下一条边。
在这里插入图片描述
在这里插入图片描述

例如:

  • A指向B和D。
    A顶点顺着firstedge指针,往后找相连接的第一条边,就是A指向B边。
    在边结点的iLink指针,继续寻找,和i结点相连接的下一条边,就是A指向D的边。
    找完了以后没有和A相连接的了,那么该结点的iLink指针是NULL

  • B指向ACE这些结点与他相连接。
    B结点的fistedge指针往后找,找到第一条边的信息,也就是A和B相连接的边。
    在边结点的jLink指针,继续寻找,和j结点相连接的下一条边,就是BC结点中间的边。
    直到jLink结点的指向NULL。说明找完所有的结点。

三、删除边和结点

  • 例如我们要删除A和B之间的边,直接删除对应的边结点即可。
    修改两个指针:
    1、删除结点之前,顺着iLink指针找到下一条边。让该节点连接即可。
    让A结点的firstedge的指针.指向后边的边即可。
    同理B结点。

  • 删出E顶点。
    1.删除E的数据之外,删除和E相连的所有边的信息, 将边的ijLink的信息赋值给上一个ijLink。

四、空间复杂度

邻接多重表不需要存储边的多余的信息,
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43989347/article/details/116862626
今日推荐