当前位置:首页 » 存储配置 » 稀疏图的存储

稀疏图的存储

发布时间: 2023-02-11 02:03:27

1. 图的五种存储结构

图的邻接矩阵(Adjacency Matrix): 图的邻接矩阵用两个数组来表示图。一个一维数组存储图中顶点信息,另一个二维数组(一般称之为邻接矩阵)来存储图中的边或者弧的信息。从邻接矩阵中我们自然知道一个顶点的度(对于无向图)或者有向图中一个顶点的入度出度信息。

假设图G有n个顶点,则邻接矩阵是一个n*n的方阵。
1.对于如果图上的每条边不带权值来说,那么我们就用真(一般为1)和假(一般为0)来表示一个顶点到另一个顶点存不存在边。下面是一个图的邻接矩阵的定义:

邻接矩阵法实现带权值的无向图的创建如下:

按照如图输入各边(不重复)

测试程序如下:

结果可得该矩阵,证明创建树成功。 假设n个顶点e条边的创建,createGraph算法的时间复杂度为O(n+n*n+e)。如果需要创建一个有向图,那么和上面一样一个一个录入边下标和权值。

邻接矩阵这种存储结构的优缺点: 缺点是对于边数相对顶点较少的稀疏图来说会存在极大的空间浪费。假设有n个顶点,优点是对于有向完全图和无向完全图来说邻接矩阵是一种不错的存储结构,浪费的话也只浪费了n个顶点的容量。

在树的存储结构一节中我们提到对于孩子表示法的第三种:用一段连续的存储单元(数组)存储树中的所有结点,利用一个单链表来存储数组中每个结点的孩子的信息。对于图的存储结构来说,我们也可以利用这种方法实现图的存储

邻接表(Adjacency List): 这种数组与链表相结合的存储方法叫做邻接表。1.为什么不也用单链表存储图的结点信息呢?原因就是数组这种顺序存储结构读取结点信息速率快。对于顶点数组中,每个数据元素还需要存储一个指向第一个邻接顶点的指针,这样才可以查找边的信息2.图中每个顶点Vi(i > 0)的所有邻接点构成一个线性表 (在无向图中这个线性表称为Vi的边表,有向图中称为顶点作为弧尾的出边表) ,由于邻接点的不确定性,所以用链表存储,有多少个邻接点就malloc一个空间存储邻接点,这样更不会造成空间的浪费(与邻接矩阵相比来说)。3.对于邻接表中的某个顶点来说,用户关心的是这个顶点的邻接点,完全可以遍历用单链表设计成的边表或者出边表得到,所以没必要设计成双链表。

邻接表的存储结构:
假设现在有一无向图G,如下图:

从邻接表结构中,知道一个顶点的度或者判断两个顶点之间是否存在边或者求一个顶点的所有邻接顶点是很容易的。

假设现在有一有向图G,如下图:

无向图的邻接表创建示例如下:

假设在上图(无向图)中的V0V1V2V3顶点值为ABCD,则依据下面测试程序可得结果:

邻接表的优缺点: 优点是:邻接表存储图,既能够知道一个顶点的度和顶点的邻接结点的信息,并且更不会造成空间的浪费。缺点是邻接表存储有向图时,如果关心的是顶点的出度问题自然用邻接表结构,但是想了解入度需要遍历图才知道(需要考虑逆邻接表)。

十字链表(Orthogonal List) :有向图的一种存储方法,它把邻接表和逆邻接表结合起来,因此在十字链表结构中可以知道一个顶点的入度和出度情况。
重新定义顶点表的结点如下图:

现在有一有向图如下图:

则它的存储结构示意图为:

其定义如下:

十字链表是用来存储有向图的,这样可以看出一个顶点的出入度信息。对于无向图来说完全没必要用十字链表来存储。

在无向图中,因为我们关注的是顶点的信息,在考虑节约空间的情况下我们利用邻接表来存储无向图。但是如果我们关注的是边的信息,例如需要删除某条边对于邻接表来说是挺繁琐的。它需要操作两个单链表删除两个结点。因此我们仿照十字链表的方式对边表结点结构重新定义如下图:

它的邻接多重表结构为:

多重邻接表的优点:对于边的操作相比于邻接表来说更加方便。比如说我们现在需要删除(V0,V2)这条边,只需将69步骤中的指针改为nullptr即可。

边集数组(edgeset array): 边集数组是由两个数组组成,一个存储顶点信息,另一个存储边的信息,这个边数组中的每个数据元素由起点下标,终点下标,和权组成(如果边上含有权值的话)。
边数组结构如下图:

边集数组实现图的存储的优缺点:优点是对于边的操作方便快捷,操作的只是数组元素。比如说删除某条边,只需要删除一个数组元素。缺点是:对于图的顶点信息,我们只有遍历整个边数组才知道,这个费时。因此对于关注边的操作来说,边集数组更加方便。

2. 设有一稀疏图G,则G采用什么存储较省空间

搜一下:设有一稀疏图G,则G采用什么存储较省空间

3. 设有一稀疏图G,则G采用什么存储较省空间

G采用邻接表存储较省空间。

邻接表,存储方法跟树的孩子链表示法相类似,是一种顺序分配和链式分配相结合的存储结构。如这个表头结点所对应的顶点存在相邻顶点,则把相邻顶点依次存放于表头结点所指向的单向链表中。

对于无向图来说,使用邻接表进行存储也会出现数据冗余,表头结点A所指链表中存在一个指向C的表结点的同时,表头结点C所指链表也会存在一个指向A的表结点。

(3)稀疏图的存储扩展阅读:

表示法

n个顶点e条边的无向图的邻接表表示中有n个顶点表结点和2e个边表结点。(换句话说,每条边(i,j)在邻接表 中出现两次:一次在关于i的邻接表中,另一次在关于j的邻接表中)。

对于有向图,vi的邻接表中每个表结点都对应于以vi为始点射出的一条边。因此,将有向图的邻接表称为出边表。对于无向图来说,使用邻接表进行存储也会出现数据冗余,表头结点A所指链表中存在一个指向C的表结点的同时,表头结点C所指链表也会存在一个指向A的表结点。

4. 回路是简单路径 存储稀疏图,用邻接矩阵比邻接表更省空间

1、如果简单路径定义为除了头尾可以重复其他顶点不能重复,则第一句就是对的,不然不对
2、存储稀疏图,用邻接表比邻接矩阵更省空间,因此第二句错的
3、有向无环图才可以有拓扑序列,因此第三句对的

5. 稀疏矩阵一般的压缩存储方法有两种

分别是三元组和十字链表。

三元组是指形如((x,y),z)的集合(这就是说,三元组是这样的偶,其第一个射影亦是一个偶),常简记为(x,y,z)。

三元组是计算机专业的一门公共基础课程——数据结构里的概念。主要是用来存储稀疏矩阵的一种压缩方式,也叫三元组表。假设以顺序存储结构来表示三元组表(triple table),则得到稀疏矩阵的一种压缩存储方式,即三元组顺序表,简称三元组表。

十字链表(Orthogonal List)是有向图的另一种链式存储结构。该结构可以看成是将有向图的邻接表和逆邻接表结合起来得到的。用十字链表来存储有向图,可以达到高效的存取效果。同时,代码的可读性也会得到提升。

拓展资料:

十字链表(Orthogonal List)是有向图的另一种链式存储结构。可以看成是将有向图的邻接表和逆邻接表结合起来得到的一种链表。在十字链表中,对应于有向图中每一条弧都有一个结点,对应于每个定顶点也有一个结点。

十字链表之于有向图,类似于邻接表之于无向图。

也可以理解为 将行的单链表和列的单链表结合起来存储稀疏矩阵称为十字链表, 每个节点表示一个非零元素。

三元组解释:

1、所谓“三元组”是指图形的几何元素构成、图线间的拓扑关系和尺寸约束。如果一组图形的前二元相同而只是尺寸大小不同,则这组图形构成一族形状相同的系列化图形。

2、把组成一个元素的三个数称为三元组。一个三元组包含以下三部分的内容SDO_STARTING_OFFSET表明每个几何元素的第一个坐标在SDO_ORDINATES数组中的存储位置。

3、…Mt:N2)的表示称为三元组...…Mt称为标号,N1、N2为结点R为关系。当n≠0时,称Li为对结点N1的修饰。t≠0时,称Mj为对结点N2的修饰。

参考资料:网络:十字链表

网络:三元组

6. 图的表示:如何存储微博、微信等社交网络中的好友关系

x博中,两个人可以互相关注,互加好友,那如何存储这些社交网络的好友关系呢?

这就要用到:图。

和树比起来,这是一种更加复杂的非线性表结构。

树的元素称为节点,图中元素叫作顶点(vertex)。图中的一个顶点可以与任意其他顶点建立连接关系,这种建立的关系叫作边(edge)。

社交网络就是典型的图结构。

把每个用户看作一个顶点。如果两个用户之间互加好友,就在两者之间建立一条边。
所以,整个微信的好友关系就可用一张图表示。
每个用户有多少个好友,对应到图中就叫作顶点的度(degree),即跟顶点相连接的边的条数。

不过微博的社交关系跟微信还有点不同,更复杂一点。微博允许单向关注,即用户A关注用户B,但B可不关注A。

这就引入边的“方向”。

A关注B,就在图中画一条从A到B的带箭头的边,表示边的方向。A、B互关,就画一条从A指向B的边,再画一条从B指向A的边,这种边有方向的图叫作“有向图”。边没有方向的图也就叫“无向图”。

无向图中有“度”:一个顶点有多少条边。
有向图中,把度分为:

QQ社交关系更复杂,不仅记录用户之间的好友关系,还记录了两个用户之间的亲密度,如何在图中记录这种好友关系亲密度呢?
这就要用到带权图(weighted graph),每条边都有个权重(weight),可以通过这个权重来表示QQ好友间的亲密度。

最直观的一种存储方法,邻接矩阵(Adjacency Matrix)。

依赖一个二维数组:

无向图,若A[i][j]==1,则A[j][i]==1。实际上,只需存储一个即可。即无向图的二维数组,如果将其用对角线划分为上下两部分,则只需利用上或下面这样一半空间就够了,另外一半其实完全浪费。
如果存储的是稀疏图(Sparse Matrix),即顶点很多,但每个顶点的边并不多,则更浪费空间。
如微信有好几亿用户,对应到图就是好几亿顶点。但每个用户好友并不很多,一般也就三五百个而已。如果我们用邻接矩阵来存储,那绝大部分的存储空间都被浪费了。

但这也并不是说,邻接矩阵的存储方法就完全没有优点。首先,邻接矩阵的存储方式简单、直接,因为基于数组,所以在获取两个顶点的关系时,就非常高效。其次,用邻接矩阵存储图的另外一个好处是方便计算。这是因为,用邻接矩阵的方式存储图,可以将很多图的运算转换成矩阵之间的运算。比如求解最短路径问题时会提到一个Floyd-Warshall算法,就是利用矩阵循环相乘若干次得到结果。

针对上面邻接矩阵比较浪费内存空间,另外一种图存储,邻接表(Adjacency List)。

有点像散列表?每个顶点对应一条链表,链表中存储的是与这个顶点相连接的其他顶点。图中画的是一个有向图的邻接表存储方式,每个顶点对应的链表里面,存储的是指向的顶点。对于无向图来说,也是类似的,不过,每个顶点的链表中存储的,是跟这个顶点有边相连的顶点,你可以自己画下。

如上图示例,若要确定是否存在一条从顶点2到顶点4的边,就要遍历顶点2的链表,看其中是否存在顶点4,而链表存储对缓存不友好。所以邻接表查询两个顶点之间的关系较为低效。

基于链表法解决冲突的散列表中,若链过长,为提高查找效率,可将链表换成其他更高效数据结构,如平衡二叉查找树。
邻接表长得很像散列。所以,也可将邻接表同散列表一样进行“优化”。

可将邻接表中的链表改成平衡二叉查找树。实际可选用红黑树。即可更快速查找两个顶点之间是否存在边。
这里的二叉查找树也可换成其他动态数据结构,如跳表、散列表。
还可将链表改成有序动态数组,通过二分查找快速定位两个顶点之间是否存在边。

虽然微博有向图,微信是无向图,但对该问题,二者思路类似,以微博为例。

数据结构服务于算法,选择哪种存储方法和需支持的操作有关。
对于微博用户关系,需支持如下操作:

因为社交网络是一张稀疏图,使用邻接矩阵存储比较浪费存储空间。所以,这里采用邻接表。

但一个邻接表存储这种有向图也是不够的。查找某用户关注了哪些用户很容易,但若想知道某用户都被哪些用户关注了,即粉丝列表就没法了。

因此,还需一个逆邻接表,存储用户的被关注关系:

基础的邻接表不适合快速判断两个用户是否为关注与被关注关系,所以进行优化,将邻接表的链表改为支持快速查找的动态数据结构。

因需按照用户名称首字母排序,分页获取用户的粉丝列表或关注列表,跳表最合适:插入、删除、查找都非常高效,时间复杂度 ,空间复杂度稍高,是 。
跳表存储数据先天有序,分页获取粉丝列表或关注列表,非常高效。

对小规模数据,如社交网络中只有几万、几十万个用户,可将整个社交关系存储在内存,该解决方案没问题。

可通过哈希算法等数据分片方案,将邻接表存储在不同机器:
如下图,在机器1上存储顶点1,2,3的邻接表,在机器2上,存储顶点4,5的邻接表。逆邻接表的处理方式也一样。当要查询顶点与顶点关系的时候,我们就利用同样的哈希算法,先定位顶点所在的机器,然后再在相应的机器上查找。

还能借助外部存储(比如硬盘),因为外部存储的存储空间比内存多很多:
如用下表存储这样一个图。为高效支持前面定义的操作,可建多个索引,比如第一列、第二列,给这两列都建立索引。

7. 1.设有一稠密图G,则G采用( )存储较省空间,设有一稀疏图G,则G采用( )存储较省空间

邻接矩阵
邻接表

8. 稀疏图为什么用邻接表存储而不用邻接矩阵我知道是空间效率问题,怎么个说啊谢谢大神!

既然是稀疏图 那么每个节点的邻居节点数目肯定少咯 当然用邻接表(N个节点,用N*m个位置,m为每个节点的平均邻居数目)
要是用邻接矩阵的话 每个节点都要给邻居空N-1个位置(N个节点,需要N*N个位置)
当m远小于N时(稀疏图就符合这种情况),当然邻接表省空间。

9. 关于数据结构中图的储存方式的选择

首先你要明白,邻接链表存图的空间复杂度与图中边的数量有关(O(N+E) E表示图中边的数目),而数组存图空间复杂度与点数有关(O(N^2)N表示点数)
看点的数量,如果点的数量不是很大(比如几百个左右或者更小)那么二者都可以选择。
如果点的数量过大的话,用数组存储稀疏图会造成大量的空间浪费,此时选择使用邻接表更好。

10. 邻接表与邻接矩阵的异同点有哪些

(1)联系:邻接表中每个链头后的所有边表结点对应邻接矩阵中的每一行,邻接表中的每个边表结点对应邻接矩阵该行的一个非零元素。

(2)区别:

①对于任一确定的无向图,邻接矩阵是唯一的(行列号与顶点编号一致),但邻接表不唯一(链接次序与顶点编号无关)。

②邻接矩阵的空间复杂度为0(n2),而邻接表的空间复杂度为0(n+e)。

③在邻接表上容易找到任意一顶点的第一个邻接点和下一个邻接点,但要判定任意两个顶点(vi,vj)之间是否有边或弧相连,则需搜索第i个或第j个链表,还不及邻接矩阵方便。

④邻接矩阵多用于稠密图的存储(e接近n(n-1)/2),而邻接表多用于稀疏图的存储(e<<n2)。

热点内容
旧安卓如何刷入最新安卓 发布:2025-07-14 20:16:14 浏览:762
服务器或网络不给力是什么意思 发布:2025-07-14 20:15:36 浏览:317
爬网站数据库 发布:2025-07-14 20:15:20 浏览:518
邵雍的算法 发布:2025-07-14 20:13:49 浏览:118
离线烧录加密 发布:2025-07-14 20:12:13 浏览:619
奥迪怎么查配置 发布:2025-07-14 20:12:07 浏览:831
java视频编程 发布:2025-07-14 19:49:22 浏览:523
初始密码是多少年 发布:2025-07-14 19:34:12 浏览:240
ipadair2存储 发布:2025-07-14 19:26:58 浏览:620
安卓手机屏幕是不是原装怎么看 发布:2025-07-14 19:26:50 浏览:708