std :: vector或std :: list for std :: unordered_map buckets?

时间:2014-03-15 21:05:48

标签: c++ list vector unordered-map

当两个键映射到std::ordered_map<T>中的同一个存储桶时,首选数据结构是什么?我不确定使用std::vector<T>(在达到容量但需要快速迭代时需要复制所有元素)或std::list<T>是否更容易添加新元素慢一点迭代?

的std ::矢量

  • 快速迭代元素
  • 如果需要将所有元素复制到新内存中,则会出现容量不足

的std ::列表

  • 快速添加/删除节点
  • 不能作为不在连续内存中的元素进行迭代

1 个答案:

答案 0 :(得分:0)

即使不知道您的确切使用模式和工作量,我也会说std::vector更好。大部分时间都是如此,我将尝试解释下面的原因。

  1. 大多数情况下,您在哈希表中执行的查找比插入更多。查找需要对存储桶进行迭代,插入需要添加元素并可能需要调整大小。因此,针对更常见的用例进行优化更有意义。

  2. 每个插入内部都需要进行查找,因此您至少会有与insert相同的查找次数;通常更多。

  3. 大多数情况下,每个桶的平均密钥数量很少。这转化为使用小向量与小列表。调整一个小向量(包括复制元素)的速度很快。

  4. 这个矢量“调整大小”通常不会经常发生,所以你不必非理性地害怕它。 (虽然你应该注意,当向量很小时,调整大小的确经常发生。对于我所知道的所有实现都是如此,但是纠正/规避它也是微不足道的。)

  5. 对矢量的迭代很多比列表上的迭代更快。 很多

  6. 即使调整大小和复制(或移动)矢量也可以像在列表中添加元素一样快(或几乎同样快)。

  7. 通过在数据类型中提供适当的“移动”支持,调整向量的大小甚至可以降低开销。

  8. 您可以使用向量预分配一些元素,几乎完全消除了存储桶中的所有大小调整。例如,如果您知道99%的桶将包含3个或更少的键,则可以为每个向量保留3或4个元素,并忘记调整大小(几乎。)

  9. 向量(特别是当它们的元素类型很小时)比链接列表更节省空间。一个std::list需要为每个元素保留两个额外的指针,这可能是一个巨大的开销(对于8-16个字节的元素,50%-200%,具体取决于你是32位还是64位。)

  10. 由于它们的大小较小且内存连续,因此向量通常是一种更快,更好的数据结构。

  11. 最终,您必须在自己的代码库中以及自己的工作负载和使用模式中进行自己的度量和基准测试。没有完整的信息,没有人能给你一个明确的答案。因此,如果您的元素非常大,不可移动的对象,并且您主要执行插入/删除和很少的查找,那么请继续使用链接列表。否则,请使用矢量。

  12. 您可以查看this benchmark,比较vector,list和deque。它可能会进一步帮助您决定使用矢量!