图的几种表示方法
网络优化研究的是网络上的各种优化模型与算法。为了在计算机上实现网络优化的 算法,首先我们必须有一种方法(即数据结构)在计算机上来描述图与网络。一般来说, 算法的好坏与网络的具体表示方法,以及中间结果的操作方案是有关系的。这里我们介 绍计算机上用来描述图与网络的 5 种常用表示方法:邻接矩阵表示法、关联矩阵表示法、 弧表表示法、邻接表表示法和星形表示法。
在下面数据结构的讨论中,我们首先假设 G = (V, A) 是一个简单有向图,|V |= n,| A |= m ,并假设V 中的顶点用自然数1,2,....,n
表示或编号, A 中的弧用自然数1,2,...,m
表示或编号。对于有多重边或无向网络的情 况,我们只是在讨论完简单有向图的表示方法之后,给出一些说明。
(i)邻接矩阵表示法
邻接矩阵表示法是将图以邻接矩阵(adjacency matrix)的形式存储在计算机中。图 **G = (V, A)**的邻接矩阵是如下定义的: C 是一个 n × n 的 0 −1矩阵,即
也就是说,如果两节点之间有一条弧,则邻接矩阵中对应的元素为 1 ;否则为 0 。 可以看出,这种表示法非常简单、直接。但是,在邻接矩阵的所有 n^2
个元素中,只有 m 个为非零元。如果网络比较稀疏,这种表示法浪费大量的存储空间,从而增加了在网络 中查找弧的时间。
对于图 2 所示的有向图,可以用邻接矩阵表示为
同样,对于网络中的权,也可以用类似邻接矩阵的n × n 矩阵表示。只是此时一条 弧所对应的元素不再是 1,而是相应的权而已。如果网络中每条弧赋有多种权,则可以 用多个矩阵表示这些权。
(ii)关联矩阵表示法
在关联矩阵中,每行对应于图的一个节点,每列对应于图的一条弧。如 果一个节点是一条弧的起点,则关联矩阵中对应的元素为 1;如果一个节点是一条弧的 终点,则关联矩阵中对应的元素为 −1;如果一个节点与一条弧不关联,则关联矩阵中 对应的元素为 0。
对于简单图,关联矩阵每列只含有两个非零元(一个 +1,一个 −1)。 可以看出,这种表示法也非常简单、直接。但是,在关联矩阵的所有nm 个元素中,只 有2m 个为非零元。如果网络比较稀疏,这种表示法也会浪费大量的存储空间。但由于 关联矩阵有许多特别重要的理论性质,因此它在网络优化中是非常重要的概念。
对于图2所示的图,如果关联矩阵中每列对应弧的顺序为(1,2),(1,3),(2,4), (3,2),(4,3),(4,5),(5,3)和(5,4)
,则关联矩阵表示为
————————
同样,对于网络中的权,也可以通过对关联矩阵的扩展来表示。例如,如果网络中 每条弧有一个权,我们可以把关联矩阵增加一行,把每一条弧所对应的权存储在增加的 行中。如果网络中每条弧赋有多个权,我们可以把关联矩阵增加相应的行数,把每一条 弧所对应的权存储在增加的行中。
弧表表示法
弧表表示法将图以弧表(arc list)的形式存储在计算机中。所谓图的弧表,也就是 图的弧集合中的所有有序对。弧表表示法直接列出所有弧的起点和终点,共需2m 个存 储单元,因此当网络比较稀疏时比较方便。此外,对于网络图中每条弧上的权,也要对 应地用额外的存储单元表示。
图2所示的图,假设弧**(1,2),(1,3),(2,4),(3,2), (4,3),(4,5),(5,3)和(5,4)**上的权分别为 8,9,6,4,0,3,6 和 7,则弧表表示如表 1 所示。
为了便于检索,一般按照起点、终点的字典序顺序存储弧表,如上面的弧表就是按 照这样的顺序存储的。
邻接表表示法
邻接表表示法将图以邻接表(adjacency lists)的形式存储在计算机中。所谓图的 邻接表,也就是图的所有节点的邻接表的集合;而对每个节点,它的邻接表就是它的所 有出弧。邻接表表示法就是对图的每个节点,用一个单向链表列出从该节点出发的所有 弧,链表中每个单元对应于一条出弧。为了记录弧上的权,链表中每个单元除列出弧的 另一个端点外,还可以包含弧上的权等作为数据域。图的整个邻接表可以用一个指针数 组表示。
这是一个 5 维指针数组,每一维(上面表示法中的每一行)对应于一个节点的邻接 表,如第 1 行对应于第 1 个节点的邻接表(即第 1 个节点的所有出弧)。**每个指针单元 的第 1 个数据域表示弧的另一个端点(弧的头),后面的数据域表示对应弧上的权。**如 第 1 行中的“2”表示弧的另一个端点为 2(即弧为(1,2)),“8”表示对应弧(1,2)上的 权为 8;“3”表示弧的另一个端点为 3(即弧为(1,3)),“9”表示对应弧(1,3)上的权 为 9。又如,第 5 行说明节点 5 出发的弧有(5,3)、(5,4),他们对应的权分别为 6 和 7。
对于有向图G = (V, A),一般用 A(i) 表示节点i 的邻接表,即节点i 的所有出弧构 成的集合或链表(实际上只需要列出弧的另一个端点,即弧的头)。例如上面例子, **A(1) = {2,3}, A(5) = {3,4}**等。
星形表示法
星形(star)表示法的思想与邻接表表示法的思想有一定的相似之处。对每个节点, 它也是记录从该节点出发的所有弧,但它不是采用单向链表而是采用一个单一的数组表 示。也就是说,在该数组中首先存放从节点 1 出发的所有弧,然后接着存放从节点 2 出发的所有孤,依此类推,最后存放从节点n 出发的所有孤。对每条弧,要依次存放其 起点、终点、权的数值等有关信息。这实际上相当于对所有弧给出了一个顺序和编号, 只是从同一节点出发的弧的顺序可以任意排列。此外,为了能够快速检索从每个节点出 发的所有弧,我们一般还用一个数组记录每个节点出发的弧的起始地址(即弧的编号)。 在这种表示法中,可以快速检索从每个节点出发的所有弧,这种星形表示法称为前向星 形(forward star)表示法。
例如,在例 7 所示的图中,仍然假设弧(1,2),(l,3),(2,4),(3,2),(4,3),(4,5), (5,3)和(5,4)上的权分别为 8,9,6,4,0,3,6 和 7。此时该网络图可以用前向 星形表示法表示为表 2 和表 3 。
在数组 point 中,其元素个数比图的节点数多 1(即n +1),且一定有 **point(1) = 1, point(n +1) = m +1。**对于节点i ,其对应的出弧存放在弧信息数组的位置区间为
[ point(i), point(i +1) −1], //表示记录弧信息的表中**[point[i],point[i+1]-1]都是以i**为出弧
如果 point(i) = point(i +1) ,则节点i 没有出弧。这种表示法与弧表表示法也非常相似,“记录弧信息的数组”实际上相当于有序存放的“弧表”。只是在前向星形表示法中, 弧被编号后有序存放,并增加一个数组( point )记录每个节点出发的弧的起始编号。
前向星形表示法有利于快速检索每个节点的所有出弧,但不能快速检索每个节点的 所有入弧。为了能够快速检索每个节点的所有入孤,可以采用反向星形(reverse star) 表示法:首先存放进入节点 1 的所有孤,然后接着存放进入节点 2 的所有弧,依此类推, 最后存放进入节点n 的所有孤。对每条弧,仍然依次存放其起点、终点、权的数值等有 关信息。同样,为了能够快速检索从每个节点的所有入弧,我们一般还用一个数组记录 每个节点的入孤的起始地址(即弧的编号)。
图2所示的图,可以用反向星形表 示法表示为表 4 和表 5。
如果既希望快速检索每个节点的所有出弧,也希望快速检索每个节点的所有入弧, 则可以综合采用前向和反向星形表示法。当然,将孤信息存放两次是没有必要的,可以 只用一个数组(trace)记录一条弧在两种表示法中的对应关系即可。
例如,可以在采用前向星形表示法的基础上,加上上面介绍的 rpoint 数组和如下的trace 数组即可。这相 当于一种紧凑的双向星形表示法,如表 6 所示。
对于网络图的表示法,我们作如下说明:
① 星形表示法和邻接表表示法在实际算法实现中都是经常采用的。星形表示法的优点是占用的存储空间较少,并且对那些不提供指针类型的语言(如 FORTRAN 语言 等)也容易实现。邻接表表示法对那些提供指针类型的语言(如 C 语言等)是方便的, 且增加或删除一条弧所需的计算工作量很少,而这一操作在星形表示法中所需的计算工作量较大(需要花费O(m) 的计算时间)。有关“计算时间”的观念【时间复杂度】是网络优化中需要考虑的一个关键因素。
② 当网络不是简单图,而是具有平行弧(即多重弧)时,**显然此时邻接矩阵表示法是不能采用的。**其他方法则可以很方便地推广到可以处理平行弧的情形。
③ 上述方法可以很方便地推广到可以处理无向图的情形,但由于无向图中边没有方向,因此可能需要做一些自然的修改。
例如,可以在计算机中只存储邻接矩阵的一半 信息(如上三角部分),因为此时邻接矩阵是对称矩阵。无向图的关联矩阵只含有元素 0 和 +1,而不含有 −1,因为此时不区分边的起点和终点。又如,在邻接表和星形表示 法中,每条边会被存储两次,而且反向星形表示显然是没有必要的,等等。
————————
版权声明:本文为CSDN博主「wamg潇潇」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_29831163/article/details/89785015