保持图形的有效方法(二维数组)

时间:2010-10-10 20:56:26

标签: graph multidimensional-array memory-efficient

在内存空间或构建时间方面,有没有人知道保存图形信息的更有效方法(即比将其保留为二维数组更有效)?

你可以假设它的值限制在0-255之间。

感谢名单!

4 个答案:

答案 0 :(得分:3)

以下是表示(定向)图表的几种标准方法:

对于4个节点的图表:

邻接矩阵:

  0  1  2  3 
0 F  F  T  F
1 T  F  T  T
2 T  F  F  F
3 F  F  F  F

边缘清单:

((0, 2), (1, 0), (1, 2), (1, 3), (2, 0))

邻接清单:

(
 (0, (2,)     ), 
 (1, (0, 2, 3)), 
 (2, (0,)     ),
 (4, (,)      ),
)

邻接矩阵是简单且最快的表示,但占用的内存最多(N * N,其中N是行数),除非你有一个非常密集的图形。如果你只有一个简单的未加权图,你可以通过使用位数来节省一些内存。

边缘列表很简单,但比邻接矩阵慢,如果你有一个稀疏图形(2 * M,其中M是边数),则内存效率很高。

邻接列表稍微复杂一些(因为你需要可变大小的数组),但是如果你有大量的边(2 * N + M,其中N是顶点的数量,M,则边缘列表的内存效率更高)边数)

邻接矩阵占用(N N b)空间。边缘列表采用((2 + b)* N)内存。并且邻接列表采用(2 * N + M *(1 + b))存储器。

如果您知道总是少于256个顶点(8位),并且权重小于256(8位),则邻接矩阵需要(N * N * 8)个空格。边缘列表占用(24 * N)内存。邻接列表采用(16 * N + M * 16)内存。

答案 1 :(得分:2)

如果创建后不需要修改图形,请查看压缩稀疏行(CSR)格式。来自BGL的说明:

  

CSR格式存储顶点和   在单独的数组中的边,与   这些数组的索引   对应于的标识符   分别是顶点或边缘。该   edge数组按来源排序   每个边缘,但只包含   边缘的目标。顶点   数组将偏移存储到边缘   数组,提供偏移量   从每个顶点传出的第一条边。   迭代在外边缘   图中的顶点是通过   访问edge_array [vertex_array [i]],   edge_array [vertex_array [i] +1],...,   edge_array [vertex_array [I + 1]]。这个   格式最小化内存使用到O(n +   m),其中n和m是数字   顶点和边分别。该   常数乘以n和m   基于整数的大小   需要将指数表示为   边和顶点数组,分别为(...)

Here偏移数组的一个很好的解释:

       Offset              Neighbours
   1      1    -------------->  2
   2      3    ------------     3
   3      5    ----------  |->  1
   4      9    --------  |      3
   5     10    ------  | |--->  1
   6     12    ----  | |        2
   7     14    --  | | |        4
                 | | | |        6
                 | | |  ----->  3
                 | |  ------->  6
                 | |            7
                 |  --------->  5
                 |              7
                  ----------->  5
                                6

有效插入边缘

创建后允许插入边缘可以通过将Neighbours数组基本上变成“链表”来实现。偏移点 进入第一个邻居,每个邻居包含一个Next字段。这指向下一个边缘。

来自同一来源:

        Offset                 Node  Next
   1      1    -------------->  2    2
   2      3    ------------     3   -1
   3      5    ----------  |->  1    4
   4      9    --------  |      3   -1
   5     10    ------  | |--->  1    6
   6     12    ----  | |        2    7
   7     14    --  | | |        4    8
                 | | | |        6    9
                 | | |  ----->  3   -1
                 | |  ------->  6   11
                 | |            7   -1
                 |  --------->  5   13
                 |              7   -1
                  ----------->  5   15
                                6   -1

答案 2 :(得分:1)

如果图形相当稀疏,那么您将通过将其存储为边缘列表(从节点到节点)而不是邻接矩阵来节省空间。如果所有边都是双向的,那么你当然只需要存储一次边。

答案 3 :(得分:0)

我在这里找到了有用的图表表示列表:

Graph Data Structures