【问题标题】:When std::map/std::set should be used over std::unordered_map/std::unordered_set?何时应在 std::unordered_map/std::unordered_set 上使用 std::map/std::set?
【发布时间】:2021-05-30 12:46:47
【问题描述】:

在新标准中引入了 std::unordered_map/std::unordered_set,它使用哈希函数,并且在我们不需要迭代集合的情况下,插入/删除/获取元素的平均复杂度恒定特别是,似乎没有理由使用“旧”std::map/std::set?或者当 std::map/std::set 是更好的选择时,还有其他一些情况/原因?就像他们是前任一样。更少的内存消耗,或者它们对“无序”版本的唯一优点是排序?

【问题讨论】:

  • FWIW,不要使用标准提供的无序容器。它们基本上需要是链表的向量。那里有更好的基于开源哈希的容器。我的建议是仅在需要维护排序顺序时使用std::map/std::set。否则使用基于哈希的容器。
  • 有序映射/集合的优点是它们是有序的。这真的是我能想到使用它们的唯一原因。
  • @NathanOliver 那里的“更好”哈希图(例如 absl )更适合许多用途,但不是全部。我尝试用我们图书馆中的那些替代品替换 unordered_set/map,在某些地方这是一个不错的收获,在一半的地方这是一个灾难性的损失。
  • @Johy 简单的答案是,当您需要性能时,每次使用时,请使用缓存友好的内容,在本例中为 unordered_mapunordered_set。但请记住,如果您将这些结构用于 buffers 并尝试从多线程上下文中访问它们,您可能会遇到麻烦,因为有时底层数组必须增长(listvector)。本质上,在您做出最终决定之前进行基准测试和分析。
  • @NathanOliver 从我对tessilabseilabseilskarupke 最流行的robin hoodhopscotch 实现的经验来看,除了简单之外,它们根本无法使用类型。如果你甚至需要存储smart pointers,性能只会下降,而糟糕的hash function,其中一些会简单地放弃并崩溃或内存不足。所以我建议在决定使用 std 以外的任何东西之前进行基准测试。

标签: c++ algorithm c++11 hash std


【解决方案1】:

它们是有序的,写<我们比写哈希和相等更容易。

永远不要低估易用性,因为 90% 的代码对代码性能的影响微乎其微。加快 10% 的速度可以节省您为另一种类型编写散列所花费的时间。

OTOH,一个好的哈希组合器只写一次,get-state-as-tie 使 <==hash 几乎免费。

具有基于节点的操作的容器之间的拼接保证可能会更好,因为拼接到哈希映射中并不像良好的有序容器拼接那样免费。但我不确定。

最后,迭代器失效保证不同。盲目地用无序的喵喵代替成熟的测试喵喵可能会产生错误。也许地图的失效功能对你来说是值得的。

【讨论】:

  • "一个好的哈希组合器只写一次,get-state-as-tie 使得 。"你能解释一下吗?给我详细的?
  • @John Sure。你能解释一下你理解或认识的粗体文本吗?你知道std::tie 是什么吗? ==,它与std::tie 有什么关系? < 也一样?哈希组合器是什么样的?哈希组合器和std::tie 有什么关系? (这些问题中的任何一个是或否都是合理的,但我不知道你知道什么,所以我不知道该怎么解释)
【解决方案2】:

std::set/std::mapstd::unordered_set/std::unordered_map 用于非常不同的问题领域,不能相互替代。

  1. std::set/std::map 用于问题围绕元素顺序移动并且元素访问时间平均为 O(log n) 的情况下是可以接受的。通过使用std::set/std::map,还可以检索其他信息,例如查找大于给定元素的元素数。

  2. std::unordered_set/std::unordered_map 用于元素访问在平均情况下必须具有 O(1) 时间复杂度且顺序不重要的情况,例如,如果您想将整数键的元素保留在 std::vector 中,则表示 @987654327 @ 但这不是实际的方法,因为如果键非常非常大,例如一个键是20,另一个是50000,那么只需要分配两个值std::vector,大小为50001,如果你使用@ 987654332@ 那么元素访问复杂度是 O(log n) 而不是 O(1)。在这个问题中使用了std::unordered_set/std::unordered_map,它在平均情况下通过使用hashing 提供了O(1) 恒定时间复杂度,而不会分配大空间。

【讨论】:

    猜你喜欢
    • 2019-04-01
    • 2016-03-14
    • 1970-01-01
    • 1970-01-01
    • 2022-01-13
    • 2014-04-15
    • 2015-10-22
    • 2015-10-11
    • 2014-08-10
    相关资源
    最近更新 更多