大话数据结构--图的常用存储结构

简介: 大话数据结构--图的常用存储结构

7.3.2邻接表


为了解决边数相对顶点较少的图,邻接矩阵这种结构会存在大量的空间浪费

如下:

image.png

再回忆我们在树中谈存储结构时,讲到了一种孩子表示法,将结点存入数组,并对结点的孩子进行链式存储,不管有多少孩子,也不会存在空间浪费问题。这个思路同样适用于图的存储。我们把这种数组与链表相结合的存储方法称为邻接表 (Adjacency List)。

邻接表的处理办法:

1.图中顶点用一个一维数组存储,当然,顶点也可以用单链表来存储,不过数组可以较容易地读取顶点信息,更加方便。另外,对于顶点数组中,每个数据元素还需要存储指向第一个邻接点的指针,以便于查找该顶点的边信息。

2.图中每个顶点Vi的所有邻接点构一个线性表,由于邻接点的个数不定,所以用单链表存储,无向图称为顶点Vi的边表,有向图则称为顶点Vi作为弧尾的出表。

image.png

上图中的V1顶点与V0、V2互为邻接点,则在V1的边表中,adjvex分别为V0的0和V2的2

下面解释什么是边表

顶点表的各个节点由data和firstedge两个域表示,data是数据域,存储顶点的信息,firstedge是指针域,指向边表(因为它是无向图,所以叫边表) 的第一个结点,即此顶点的第一个邻接点。边表结点由adjvex和next两个域组成。adjvex 是邻接点域,存储某顶点的邻接点在顶点表中的下标,next 则存储指向边表中下一个结点的指针。

在有向图中,邻接表的结构是类似的

我们可以建立一个有向图的逆邻接表,即对每个顶点Vi都建立一个链接为v为弧头的表

image.png

image.png

此时我们很容易就可以算出某个顶点的入度或出度是多少,判断两顶点是否存在弧也很容易实现。

对于带权值的网图,可以在边表结点定义中再增加一个weight的数据域,存储权值信息即可

image.png


7.3.3十字链表


那么对于有向图来说,邻接表是有缺陷的。关心了出度问题,想了解入度就必须要遍历整个图才能知道,反之,逆邻接表解决了入度却不了解出度的情况。有没有可能把邻接表与逆邻接表结合起来呢?答案是肯定的,就是把它们整合在一起。这就是我们现在要讲的有向图的一种存储方法:十字链表(Orthogonal List)。

重新定义结点表结点结构

data firstin firstout

其中firstin表示入边表头指针,指向该顶点的入边表中第一个结点, firstout 表示出边表头指针,指向该顶点的出边表中的第一个结点。

重新定义边表结点结构

image.png

其中tailvex 是指弧起点在顶点表的下标,headvex 是指弧终点在顶点表中的下标,headlink是指入边表指针域,指向终点相同的下一条边,tallink 是指边表指针域,指向起点相同的下一条边。 如果是网,还可以再增加一个 weight域来存储权值。

实例如下:

image.png

以顶点V0来说,firstout指向的是出边表中的第一个结点V3所以tailvex和headvex是03(就是数组下标),那为什么headlink和taillink为空了呢,因为没用终点和V0一样的结点了(指向V3的),那为什么taillink也为空呢,因为没有和V0一样起点的结点(从V0出发)了呀!

图中也有些例子,可以多理解理解

同志们一定好好看看和理解这个图!!!

十字链表的好处就是因为把邻接表和逆邻接表整合在了一起,这样很容易找到以Vi为尾的弧,也容易找到以vi为头的弧,从而更容易求得顶点的出度和入度

缺点就是结构复杂了一点,在有向图的应用中,十字链表是非常好的数据结构模型


7.3.4邻接多重表


十字链表对有向图的存储结构进行了优化

在无向表的应用中,关注的重点是顶点,邻接表是好的选择

如果关注的是边的操作,就需要更简单的方式

对边表结点结构重新定义

image.png

其中ivex和jvex是与某条边依附的两个顶点在顶点表中下标。

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

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

下图告诉我们它有4个顶点和5条边,显然,我们就应该先将4个顶点和5条边的边表结点画出来。由于是无向图,所以ivex是0、jvex是1还是反过来都是无所谓的,不过为了绘图方便,都将ivex值设置得与一旁的顶点下标相同。

image.png

好,我们来分析这个图

firstedge是指针域,指向边表的第一个结点,ivex和jvex是依附于边的顶点坐标的下标(注意是顶点坐标的下标),比如图中的0和1,那么它们就代表顶点V0和顶点V1中间的那条边

那么ilink和jlink是什么呢?

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

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

实例如图所示:

image.png

看上面的连线,firstedge指向一条边,顶点下标和ivex的值相同,继续,顶点V0有三个边跟它有关v0v1,v0v2,v0v3

所以连线5,6满足指向下一条依附于顶点的v0的边的目标,ilink指向的结点的jvex一定要和它本身的ivex值相同。连线7就是指v1,v0这条边,它是相当于顶点v1指向v1,v2边后的下一条。v2有三条依附,所以在连线3后就有了8跟9.连线10的就是顶点v3在连线4后下一条边。

图上共5条边所以有10条连线,符合预期

邻接多重表与邻接表的差别,仅仅是在于同一条边在邻接表中用两个结点表示,而在邻接多重表中只有一个结点。 这样对边的操作就方便多了,若要删除左图的(V0,V2) 这条边,只需要将右图的⑥⑨的链接指向改为^即 可。各种基本操作的实现也和邻接表是相似的


7.3.5边集数组


边集数组是由两个一维数组构成。一个是存储顶点的信息;另一个是存储边的信息,这个边数组每个数据元素由一条边的起点下标(begin)、终点下标(end) 和权(weight)组成

实例如下:

image.png

这个结构很好理解,看图就能看懂



相关文章
|
2月前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
103 16
|
3月前
|
存储 安全 数据库
除了 HashMap,还有哪些数据结构可以实现键值对存储?
【10月更文挑战第11天】 除了`HashMap`,其他常见支持键值对存储的数据结构包括:`TreeMap`(基于红黑树,键有序)、`LinkedHashMap`(保留插入顺序)、`HashTable`(线程安全)、`B-Tree`和`B+Tree`(高效存储大量数据)、`SkipList`(通过跳跃指针提高查找效率)及`UnorderedMap`(类似`HashMap`)。选择合适的数据结构需根据排序、并发、存储和查找性能等需求。
|
4月前
|
存储 Java
java数据结构,线性表链式存储(单链表)的实现
文章讲解了单链表的基本概念和Java实现,包括头指针、尾节点和节点结构。提供了实现代码,包括数据结构、接口定义和具体实现类。通过测试代码演示了单链表的基本操作,如添加、删除、更新和查找元素,并总结了操作的时间复杂度。
java数据结构,线性表链式存储(单链表)的实现
|
3月前
|
存储 编译器 C++
【初阶数据结构】掌握二叉树遍历技巧与信息求解:深入解析四种遍历方法及树的结构与统计分析
【初阶数据结构】掌握二叉树遍历技巧与信息求解:深入解析四种遍历方法及树的结构与统计分析
|
3月前
探索顺序结构:栈的实现方式
探索顺序结构:栈的实现方式
|
4月前
|
存储 人工智能 C语言
数据结构基础详解(C语言): 栈的括号匹配(实战)与栈的表达式求值&&特殊矩阵的压缩存储
本文首先介绍了栈的应用之一——括号匹配,利用栈的特性实现左右括号的匹配检测。接着详细描述了南京理工大学的一道编程题,要求判断输入字符串中的括号是否正确匹配,并给出了完整的代码示例。此外,还探讨了栈在表达式求值中的应用,包括中缀、后缀和前缀表达式的转换与计算方法。最后,文章介绍了矩阵的压缩存储技术,涵盖对称矩阵、三角矩阵及稀疏矩阵的不同压缩存储策略,提高存储效率。
494 8
|
3月前
|
存储 算法
【数据结构】二叉树——顺序结构——堆及其实现
【数据结构】二叉树——顺序结构——堆及其实现
|
4月前
|
存储 算法 C语言
数据结构基础详解(C语言): 二叉树的遍历_线索二叉树_树的存储结构_树与森林详解
本文从二叉树遍历入手,详细介绍了先序、中序和后序遍历方法,并探讨了如何构建二叉树及线索二叉树的概念。接着,文章讲解了树和森林的存储结构,特别是如何将树与森林转换为二叉树形式,以便利用二叉树的遍历方法。最后,讨论了树和森林的遍历算法,包括先根、后根和层次遍历。通过这些内容,读者可以全面了解二叉树及其相关概念。
|
4月前
|
存储 机器学习/深度学习 C语言
数据结构基础详解(C语言): 树与二叉树的基本类型与存储结构详解
本文介绍了树和二叉树的基本概念及性质。树是由节点组成的层次结构,其中节点的度为其分支数量,树的度为树中最大节点度数。二叉树是一种特殊的树,其节点最多有两个子节点,具有多种性质,如叶子节点数与度为2的节点数之间的关系。此外,还介绍了二叉树的不同形态,包括满二叉树、完全二叉树、二叉排序树和平衡二叉树,并探讨了二叉树的顺序存储和链式存储结构。
|
4月前
|
存储 算法 C语言
C语言手撕数据结构代码_顺序表_静态存储_动态存储
本文介绍了基于静态和动态存储的顺序表操作实现,涵盖创建、删除、插入、合并、求交集与差集、逆置及循环移动等常见操作。通过详细的C语言代码示例,展示了如何高效地处理顺序表数据结构的各种问题。