【问题标题】:How efficient is iterating through an unordered_set?遍历 unordered_set 的效率如何?
【发布时间】:2016-02-28 18:31:13
【问题描述】:

遍历 unordered_set 是否需要查看哈希表的每个桶?如果是这样,那不是非常低效吗?如果我想频繁地迭代一个集合,但仍然需要在 O(1) 时间内删除,那么 unordered_set 仍然是最好的数据结构吗?

【问题讨论】:

  • 对于所有标准 c++ 容器,迭代容器的每个元素都是 O(n)。您是否改为测试成员资格,这在集合上更快?
  • *If so, wouldn't that be very inefficient?* 为什么会“非常低效”?哈希表存储在连续的内存中,因此检查存储桶并不是特别繁重,性能方面。这显然不如检查vector 快,但也不像通过set 运行的缓存未命中。
  • 据我了解,桶的数量应该大于预期的元素数量,所以我认为遍历所有桶然后访问每个桶的内容需要更多时间。跨度>

标签: c++ c++11 stl


【解决方案1】:

碰巧的是,std::unordered:set 的常见实现将所有元素链接在一起,就像std::forward_list 所做的那样,因此遍历容器基本上等同于遍历列表(详细信息here)。在任何情况下,如有疑问,请分析您的程序并查看结果是否满足您的需求。

【讨论】:

    【解决方案2】:

    遍历哈希表会比遍历vector 慢吗?是的。 vector 将连续存储其元素;哈希表需要某种方法来识别存储桶是否包含数据。一些哈希表给每个桶一个映射到同一个桶的值的链表;其他人使用其他方法。无论哪种方式,unordered_set 迭代器都需要查看每个存储桶并确定其是否为空。这不如指针算术快。

    但是,我不会将花在查看空桶上的额外时间归类为“非常低效”。仅仅因为它不如排序的vector 快​​并不意味着它效率低下。您仍然有缓存一致性,因为存储桶可能不会占用那么多内存,并且测试一个空的只是一次缓存内存获取。

    最后,每个数据结构都有权衡。如果您想要 O(1) 查找和删除,哈希表是获得它的唯一方法。这意味着迭代将比vector 花费更长的时间。但不像set那样长。

    【讨论】:

    • 为什么哈希表的迭代速度比std::set快?
    【解决方案3】:

    哈希表将数据存储在向量中,所有内容都通过将键转换为哈希数(通常为long)进行索引,该哈希数成为所需元素的向量中的索引,也有使用向量内的向量的哈希表去做这个。 如果您遍历std::unordered_set,它只需要花费O(n),因为它就像遍历std::vector

    【讨论】:

    • 肯定没那么简单吧?必须涉及稀疏数组,除非哈希函数减少到一个非常小的域,否则底层向量将是巨大的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-26
    • 2017-09-09
    • 2015-10-13
    • 2019-11-05
    • 1970-01-01
    • 2019-11-14
    相关资源
    最近更新 更多