【问题标题】:What is the best standard data structure to build a Graph?构建图的最佳标准数据结构是什么?
【发布时间】:2011-07-29 19:51:03
【问题描述】:

起初我是 C++ 的初学者,我是自学的,所以请回答的很简单......

我需要编写一个包含节点的图,每个节点都有 id 和边列表,每条边都有另一个节点 id 和距离

我正在寻找的是我应该使用什么来构建这个图,因为我想使用 dijkstra 算法来获得从一个点到另一个点的最短路径......所以搜索性能应该是我认为最重要的! !

我已经搜索了很多,现在我很困惑

提前感谢您的帮助

【问题讨论】:

标签: c++ data-structures graph performance


【解决方案1】:

您可以定义一个Edge 结构,如

struct Edge
{
    int destination;
    int weight;
};

并创建一个图表

vector<vector<Edge> > graph;

然后要访问来自顶点u 的所有边,您可以编写类似

for( int i = 0; i < graph[u].size(); ++i ) {
    Edge edge = graph[u][i];
    // here edge.destination and edge.weight give you some details.
}

您可以动态添加新边,例如从第 3 个顶点到第 7 个顶点的边,权重为 8:

Edge newEdge;
newEdge.destination = 7;
newEdge.weight = 8;
graph[3].push_back( newEdge );

等等

对于无向图,当然不要忘记添加对称边。

这应该没问题。

编辑 基本容器(std::vectorstd::liststd::map)的选择取决于用例,例如你经常用图做什么:添加/删除顶点/边,只是遍历。创建图表后,std::liststd::vector 对 Dijkstra 来说同样适用,std::vector 由于松弛阶段的顺序访问模式而更快一些。

【讨论】:

  • 这个答案我已经知道了 .. 我在问向量是否是最好的使用方法 .. 性能?哪个是更好的地图或矢量??
  • 感谢编辑,它清除了一切,但如果我想根据 id a heap sort 对图形节点和边进行排序 .. 这会使其更快吗?如果是的话..我应该用什么来做这样的事情??
  • 这些都是独立于图的通用编程问题,对吧?你应该问一个单独的问题(虽然先搜索一个)
  • 我应该根据我想要构建它的目的对我的图进行编程......所以我需要它来实现 dijkstra 有效地放入我的图将有大量的节点和边
  • @Dawnlight 如果您想进行性能编程,您通常需要这些容器,按频率顺序排列:std::vector&lt;&gt;std::unordered_map&lt;&gt;std::unordered_set&lt;&gt;。在任何用例中,所有其他容器的性能都优于这三个容器之一,它们只需要正确使用即可。
【解决方案2】:

一个包含节点的图,每个节点都有id和边列表每条边都有另一个节点id和距离

如果我们将每个节点 id 视为一个索引。我们可以如下绘制一个 nxn 的边矩阵。

这可以帮助您绘制带边的图形。

     [0][1][2][3]

[0] | 1  0  0  0|
[1] | 0  0  1  0|
[2] | 1  0  0  1|
[3] | 0  0  1  0|

因此,二维数组是矩阵的良好表示。

int maxtrix[4][4] = new int[4][4];

【讨论】:

  • 如果矩阵是稀疏的,这不是一个高效的解决方案,当 Dijkstra 算法发挥作用时,您必须假设这一点。搜索远离给定节点的非零边时,性能将下降。
  • 感谢您的评论。如果数据变成稀疏矩阵,我们必须应用更适合的算法或使用耶鲁格式。
【解决方案3】:

我个人会使用std::map&lt;Node*, std::set&lt;Node*&gt; &gt;。这非常有用,因为每次您在一个节点上时,您都可以快速找出该节点连接到哪些节点。如果需要,迭代所有节点也很容易。如果您需要在边缘放置权重,您可以使用std::map&lt;Node*, std::set&lt; std::pair&lt;int, Node*&gt; &gt; &gt;。这将比使用向量提供更好的性能,尤其是对于大型图。

【讨论】:

  • std::vector&lt;&gt; 在任何时候都优于 std::map&lt;&gt;,当您不需要订购时,std::vector&lt;&gt; 的性能优于 std::set&lt;&gt;std::map&lt;&gt;std::set&lt;&gt; 在内部都依赖于树,因此在广泛分散数据的同时具有更高的分配开销。 std::vector&lt;&gt; 在内部使用连续数组,因此 1. 内存效率高,2. 缓存效率高,3 分配效率高,4. 预取友好。真的,std::map&lt;&gt;std::set不是优化器工具箱的一部分。
  • 我真的认为,对于具有大量访问权限的大型图执行复杂算法,std::map&lt;&gt;std::set&lt;&gt; 会因为较低的指数访问时间而获胜。不过,我愿意看到证明我错了的基准。
  • 不,他们肯定不会:std::vector&lt;&gt; 的访问时间是机器级别的单指针解引用操作,而 std::map&lt;&gt;std::set&lt;&gt; 都必须遍历树,这意味着log(n) 指针取消引用操作。 特别是对于大型数据集,其中树很深。您无法击败内存中连续数组的性能。
  • 好的,是的,如果你知道你要找的东西的索引,当然vector会更好。当您不这样做时,我会考虑更多情况,然后查找向量会更糟。
猜你喜欢
  • 2011-05-15
  • 1970-01-01
  • 2011-10-23
  • 2018-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多