图的存储结构

因为任意两个顶点之间都可能存在联系,因此无法以数据元素在内存中的物理位置来表示元素之间的关系(内存物理位置是线性的,图的元素关系是平面的)。

邻接矩阵(无向图)

  • 考虑到图是由顶点和边或弧两部分组成,合在一起比较困难,那就很自然地考虑到分为两个结构来分别存储。
    顶点因为不区分大小、主次,所以用一个一维数组来存储是狠不错的选择。
    而边或弧由于是顶点与顶点之间的关系,一维数组肯定就搞不定了,那我们不妨考虑用一个二维数组来存储。
  • 图的邻接矩阵( Adjacency Matrix)存储方式是用两个数组来表示图。一个一维数组存储图中顶点信息,一个二维数组(称为邻接矩阵)存储图中的边或弧的信息。数据结构(图的存储结构)
  • 我们可以设置两个数组,顶点数组为 vertex[4]={V0,V1,V2,V3},边数组arc[4][4]为对称矩阵(0表示不存在顶点间的边,1表示顶点间存在边)。
    对称矩阵:所谓对称矩阵就是n阶矩阵的元满足a[i][j]=a[j]i。即从矩阵的左上角到右下角的主对角线为轴,右上角的元与左下角相对应的元全都是相等的。
  • 优点
    1 轻易判定任意两顶点是否有边无边。
    2 要知道某个顶点的度,其实就是这个顶点Vi在邻接矩阵中第i行(或第i列)的元素之和。
    3 求顶点Vi的所有邻接点就是将矩阵中第i行元素扫描一遍,arc[i][j]为1就是邻接点。

邻接矩阵(有向图)

有向图的存放数据结构(图的存储结构)

  • 可见顶点数组vertex[4]={V0,V1,V2,V3},弧数组arc[4][4]也是一个矩阵,但因为是有向图,所以这个矩阵并不对称。
    另外有向图是有讲究的,要考虑入度和出度,顶点V1的入度为1,正好是第V1列的各数之和,顶点V1的出度为2,正好是第V2行的各数之和。

邻接矩阵(网)

在图的术语中,我们提到了网这个概念,事实上也就是每条边上带有权的图就叫网。
数据结构(图的存储结构)
这里“∞”表示一个计算机允许的、大于所有边上权值的值。

邻接表(无向图)

邻接矩阵看上去是个不错的选择,首先是容易理解,第二是索引和编排都很舒服。
但是我们也发现,对于边数相对顶点较少的图,这种结构无疑是存在对存储空间的极大浪费。数据结构(图的存储结构)

  • 因此我们可以考虑另外一种存储结构方式,例如把数组与链表结合一起来存储,这种方式在图结构也适用,我们称为邻接表(
    Adjacencylist)。

  • 邻接表的处理方法是这样:
    图中顶点用一个一维数组存储,当然,顶点也可以用单链表来存储,不过数组可以较容易地读取顶点信息,更加方便。
    图中每个顶点Vi的所有邻接点构成一个线性表,由于邻接点的个数不确定,所以我们选择用单链表来存储。

邻接表(无向图)

数据结构(图的存储结构)

邻接表(有向图)

  • 若是有向图,邻接表结构也是类似的我们先来看下把顶点当弧尾建立的邻接表,这样很容易就可以得到每个顶点的出度:数据结构(图的存储结构)
  • 为了便于确定顶点的入度或以顶点为弧头的弧,我们可以建立一个有向图的逆邻接表
    数据结构(图的存储结构)
    此时我们很容易就可以算出禁个顶点的入度或出度是多少,判新两顶点是否存在弧也很容易实现。

邻接表(网)

对于带权值的网图,可以在边表结点定义中再增加一个数据城来存储权值即可。数据结构(图的存储结构)

十字链表

邻接表固然优秀,但也有不足,例如对有向图的处理上,有肘候需要再建立一个逆邻接表,为把邻接表和逆邻接表结合起来,就有了十字链表 (Orthogonal List)。

  • 重新定义边表结构数据结构(图的存储结构)
  • 十字链表的好处:
    因为把邻接表和逆邻接表整合在了一起,这样既容易找到以Vi为尾的弧,也容易找到以Vi为头的弧,因而容易求得顶点的出度和入度。
  • 十字链表除了结构复杂一点外,其实创建图算法的时间复杂度是和邻接表相同的,因此,在有向图的应用中,十字链表也是非常好的数据结构模型。

相关文章: