Answers:
好吧,如果您只关心空间效率,那么压缩数据结构将是最好的-但是,这当然对访问或更新不是很有效。
如果您的图的节点数量相对较少并且非常密集(假设所有可能的连接中至少有5%存在),则可能会发现创建邻接矩阵比使用边缘列表更节省空间。每个可能的(定向)连接只需要一个位,如果您有n个节点,则总共需要n * n位。
否则,如果您需要使用邻居链接,那么您就很难轻易做到每个链接都只有一个参考,因为这是您需要存储的最少信息内容。如果要反向链接,则需要两倍的链接。
您还可以尝试一些技巧。例如,您可以尝试共享链接的子集(如果A和B分别引用C,D,E,则只存储一次链接C,D,E的列表.....)。但是,这很快就会变得很复杂,我怀疑在大多数情况下是否值得这样做。
另一个技巧-假设您的图形具有合理数量的节点,则一定会通过索引来节省空间-例如,使用16位节点索引号而不是完整的指针/引用。
这将取决于您的数据结构。
对于具有无向边的密集图形,您无法真正击败代表三角矩阵的位阵列列表。一个List<BitArray>
例如。从逻辑上讲,它看起来像这样:
0123
0
11
211
3001
41010
从那里,您可以使用根BitArray的索引来索引到存储节点数据的列表中。
例如,获取节点的所有邻居将像这样:
// C#
List<Node> Nodes = /* populated elsewhere */
List<BitArray> bits = /* populated elsewhere */
public static IEnumerable<Node> GetNeighbours(int x)
{
for (int i = 0; i < bits[idx].Count; i++)
{
if (this.bits[idx][i])
yield return this.Nodes[i];
}
for (int i = 0; i < this.Nodes.Count; i++)
{
if (idx < this.bits[i].Count && this.bits[i][idx])
yield return this.Nodes[i];
}
}
(请注意,您还可以根据数据量将索引类型选择为字节或ushort或类似的东西,因为所有索引都是正数。我不认为这是微不足道的微细优化)
对于有向图,您将使用* n位数组的路径来存储连接性...除非与节点数相比非常稀疏,否则您可以转到索引的邻接表。