图结构的元素之间虽然具有“多对多”的关系,但是同样可以采用顺序存储,即使用数组有效地存储图。
集合V中所有的顶点可以利用一个一维数组存储;而集合E中所有的边可以用一个二维数组来存储,
此二维数组就称为 邻接矩阵!
设G=(V, E)是有n个(n>=1)顶点的有向图,则G的邻接矩阵是具有如下性质的 n x n 矩阵:
1, 若 <Vi, Vj> ∈ E
A[ i, j ] =
0, 若 <Vi, Vj> ∉ E
设G=(V, E)是有n个(n>=1)顶点的无向图,则G的邻接矩阵是具有如下性质的 n x n 对称矩阵:
1, 若 ( Vi, Vj ) ∈ E
A[ i, j ] = A[ j, i ] =
0, 若 ( Vi, Vj ) ∉ E
对于无向图,邻接 矩阵第 i 行(或第 i 列)的元素之和是 顶点 Vi的度;
对于有向图, 邻接矩阵第 i 行 元素之后为 顶点Vi的出度, 邻接矩阵第 i 列 的元素之和 为顶点Vi的入度。
对于带权图,也就是网 来说, 只需要把上面的 等于 1 的情况改为 权重 Wij, 把等于 0 的情况 改为 ∞
通常,图更多的是采用链表存储,具体的存储方法有 3 种,分别是邻接表、邻接多重表和十字链表。
邻接表既适用于存储无向图,也适用于存储有向图。
邻接表存储图的实现方式是,给图中的每个顶点独自建立一个链表,第i个单链表中的节点包含顶点 i 的所有邻接点。
为了便于管理这些链表,通常会将所有链表的头节点存储到数组中(也可以用链表存储)。类似于树结构的孩子表示法。
也正因为各个链表的头节点存储的是各个顶点,因此各链表在存储临界点数据时,
仅需存储该邻接顶点位于数组中的位置下标即可。
邻接表计算顶点的出度和入度
使用邻接表计算无向图中顶点的入度和出度会非常简单,只需从数组中找到该顶点然后统计此链表中节点的数量即可。
对于有向图,由于 邻接点的定义,所以只能表示指出去的点, 也就是只能计算出该顶点的出度,那么如何求入度呢?
对于利用邻接表求某顶点的入度,有两种方式:
遍历整个邻接表中的节点,统计数据域与该顶点所在数组位置下标相同的节点数量,即为该顶点的入度;
建立一个逆邻接表,该表中的各顶点链表专门用于存储以此顶点为弧头的所有顶点在数组中的位置下标。
无向图的存储可以使用邻接表,但在实际使用时,如果想对图中某顶点进行实操(修改或删除),由于邻接表中存储该顶点的节点有两个,一个是头结点,另一个时作为其他头结点的邻接点。因此需要操作两个节点。 其实对于无向图(或无向网),还可以有一种改进方法,使得每个顶点只用1个结点进行存储----邻接多重表,可看作是邻接表和十字链表的结合。