繁体   English   中英

std :: vector或std :: list for std :: unordered_map存储桶?

[英]std::vector or std::list for std::unordered_map buckets?

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

的std ::矢量

  • 快速遍历元素
  • 如果由于容量不足而需要将所有元素复制到新内存中,则很糟糕

的std ::名单

  • 快速添加/删除节点
  • 不利于迭代,因为元素不在连续内存中

即使不知道您的确切使用模式和工作量,我也会说std::vector更好。 在大多数情况下都是如此,我将在下面解释原因。

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

  2. 每个插入在内部都需要进行查找,因此您至少要进行与插入一样多的查找。 通常更多。

  3. 大多数情况下,每个存储桶的平均密钥数量很少。 转化为使用较小的矢量与较小的列表。 调整小向量的大小(涉及元素的复制)将很快。

  4. 矢量“调整大小”通常不会经常发生,因此您不必非理性地害怕它。 (尽管您应该注意,当向量很小时,调整大小的确会更频繁地发生。对于我所知道的所有实现都是如此,但纠正/规避也是不重要的。)

  5. 迭代通过矢量比迭代一个列表快得多 很多

  6. 甚至调整向量的大小和复制(或移动)向量都可以像将元素添加到列表一样快(或几乎一样快)。

  7. 通过在数据类型中提供适当的“移动”支持,调整向量大小的开销将变得更少。

  8. 您可以使用向量预先分配一定数量的元素,几乎可以完全消除存储桶中的所有大小调整。 例如,如果您知道99%的存储桶将包含3个键或更少的键,则可以为每个向量保留3或4个元素,而不必重新设置大小(几乎)。

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

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

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

您可以看一下这个基准 ,比较向量,列表和双端队列。 它可能会进一步帮助您决定使用向量!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM