【问题标题】:Good memory management strategies for graph datastructures图数据结构的良好内存管理策略
【发布时间】:2012-07-09 21:26:18
【问题描述】:

我曾多次为几位雇主实施我自己的图形数据结构。为了获得完全的访问灵活性,我经常需要使用两个类来实现这一点,一个 Node 类和一个 Edge 类。

然后一个节点将有一组传出边(可能还有传入边),并且一个边将有一个源和一个接收器(都是指向节点的托管指针)。这些图通常有循环。

我的问题是:在此类图形数据结构中管理内存的最佳方法是什么,尤其是在转换和变异图形时?由于循环的存在,它们不适合引用计数(即使您尝试使用弱指针,通常也不清楚循环的位置以及弱链接的放置位置)。

在我的各种实现中,我经常跟踪所有分配的节点和边,与图表以及图表的入口点列表分开。然后我实现了一个简单的垃圾收集器。定期应用各种图形转换(包括取消链接一些节点/边)后,我运行 gc,其中涉及:

  1. 从入口点节点开始,并将通过图形从那里可到达的所有节点和边标记为活动(通过 BFS/DFS)。
  2. 迭代整个集合中的所有节点和边,并删除上一步中未标记的任何节点和边。

这很好用(并且是标记/扫描的简单实现)。但它总是看起来有点笨拙。有没有人对此问题有任何见解或更好的替代解决方案?

【问题讨论】:

  • 你尝试过真正的 GC,比如 BoehmGC 吗?

标签: c++ memory-management data-structures graph


【解决方案1】:

当您有有限图时,不要将它们表示为指针结构。相反,使用任一

  • 边列表(vectorlist 等)和顶点列表,或者
  • 顶点到索引的映射(mapunordered_map)以及表示顶点 ij 是否连接的布尔值矩阵(二维数组)(或加权图的浮点数)。

前一种表示称为adjacency list,后者称为adjacency matrix。使用哪一个取决于您拥有的图表和您要执行的操作。两者在内存管理方面都更简单,并且通常比指针结构更高效,因为它们占用的内存更少并且倾向于保留引用的局部性。

【讨论】: