【问题标题】:Data structures for graphs图的数据结构
【发布时间】:2021-10-22 15:45:29
【问题描述】:

我目前正在写我的硕士论文。这是关于图表的。我的算法准备好了。但是现在我必须考虑有用的数据结构来表示图形以及良好运行时所需的其余部分。由于内存量大,我不允许使用邻接矩阵。由于我必须在每次迭代中检查是否存在某个边缘,因此邻接列表也没有任何意义。

首先我想到了两个相互嵌套的哈希表。所有节点都存储在第一个表中,所有相邻节点都存储在第二个表中。 但是由于我必须能够在我的算法中选择一个随机邻居,所以这也不是最优的。 此外,我必须能够在算法的每次迭代中保存边缘权重。

包含所有基本操作的列表:

  • 我需要展示边缘,如果存在某个边缘,我可以在 O (1) 中检查
  • 我必须能够在 O(1) 中选择固定节点的随机邻居
  • 我需要能够为 O (1) 中的边缘分配权重
  • 我还需要找出 O (1) 中的结度数

我可以对所有操作使用不同的数据结构。不幸的是,我的想法已经不多了。

我希望这里有人可以帮助我。

提前致谢!

丽莎

【问题讨论】:

  • 列出您需要执行的所有基本/原子操作以及它们需要多快。然后我们可以通过建议满足这些要求的数据结构来提供帮助。
  • 图应该有多少个顶点和边?

标签: data-structures hashtable graph-theory


【解决方案1】:

有关 Graph 的完整和全面的数据结构,您可以查看 CXXGraph 库。 是一个易于阅读的开源 Header-Only 库。

【讨论】:

    【解决方案2】:

    我需要展示边缘,如果存在某个边缘,我可以在 O (1) 中检查

    我需要能够为 O (1) 中的边分配权重

    这是一个从边缘到权重的哈希映射。关键只是一对顶点编号。如果这是一个无向图,则对这对中的数字进行排序,以使较小的在前。

    我必须能够在 O(1) 中选择一个固定节点的随机邻居

    我还需要在O(1)中找出一个结的度数

    这是从每个顶点到其相邻顶点数组的映射——即,图的邻接表表示,确保每个邻接表位于支持随机访问的结构中。

    【讨论】:

      【解决方案3】:

      我建议如下:

      一种映射数据结构,其中键被实现为哈希表,为您提供 O(1) 访问/插入/删除时间。此地图的键将是您的节点。

      此地图数据结构的值将是集合,也实现为哈希表,为您提供 O(1) 访问/插入/删除时间。这些集合的成员是键的相邻节点。

      对于边的权重,您有几个选择。您可以将元组插入邻接列表的集合中,其中第一个值是相邻节点,第二个值是连接这两个节点的边的权重。由于地图和集合都实现为哈希表,因此权重可以在 O(1) 时间内更新。

      您可以将节点的度数存储在单独的地图数据结构中,其中键(实现为哈希表)是节点,值是度数。这将为每个节点的度数提供 O(1) 访问/删除/更新时间。

      要实现连接到节点的随机边的 O(1) 时间,您需要使用额外的数据结构。原因是存储在集合中的边(作为哈希表)不会给我们提供一种在 O(1) 中获取随机数的方法。但是,如果我们将每个节点的边存储在类似列表/数组的数据结构中,我们可以在 O(1) 中获得介于 0 和该数组长度之间的随机索引,并在 O(1) 中访问该边。

      此方法将通过增加所需空间来满足您的时间复杂度要求,尽管空间复杂度不会增加。

      您可以创建将它们组合在一个位置的类,而不是单独的数据结构。

      如有必要,我可以添加简化的实现。

      【讨论】:

      • "这张地图的关键是你的节点。"这似乎很奇怪。我希望映射的值是节点。
      • map 的键和值中的集合成员都是节点。键是源节点,集合中的值是目标节点。这是一个邻接列表。
      • 当一个节点有多个出边时会发生什么?
      • map 数据结构的值是一个set,它本身实现为一个哈希表。这个值可以保存唯一的成员,前提是这些成员本身是可散列的。我假设成员是代表目标节点的整数,就像地图的键一样。即使节点不是整数,假设它们是包含不同类型数据的更复杂的类,也可以为它们设计散列函数。这是特定于实现的。 set 实现为哈希表,提供 O(1) 访问/删除/添加时间。
      • 这一切听起来都非常复杂,难以理解且无法维护。我想知道这一切的表现会如何。我提出的简单设计可以在 0.5 秒内对具有 0.4M 节点和 3.4M 边的图进行完整的 DFS 遍历。详情github.com/JamesBremner/PathFinder2/wiki/Performance
      【解决方案4】:

      我建议使用地图,它可以在稀疏图中快速查找顶点和边(相对于顶点数量而言,边很少)

      每个顶点存储其出边的映射,由目标顶点索引键控。该图存储在一个顶点映射中,由顶点索引作为键控。

      有关此设计的详细说明:https://github.com/JamesBremner/PathFinder2/wiki/cGraph-Class-Design

      存储库还存储实现该设计的 C++ 代码以及使用该设计的图论算法的许多实现。

      【讨论】:

        猜你喜欢
        • 2011-03-06
        • 2015-06-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多