当 std::map/std::set 应该在 std::unordered_map/std::unordered_set 上使用时?

问题描述

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

解决方法

它们是有序的,写 < us 比写散列和相等更容易。

永远不要低估易用性,因为 90% 的代码对代码性能的影响微不足道。使速度提高 10% 可以节省您为另一种类型编写哈希所花费的时间。

OTOH,一个好的散列组合器是一次写入,而 get-state-as-tie 使 <==hash 几乎免费。

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

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

,

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) 且顺序不重要的情况,例如,如果您想将整数键的元素保留在 {{1 }},这意味着 std::vector 但这不是实用的方法,因为如果键非常非常,例如一个键是 vec[10] = 10 而另一个是 20 那么只保留两个值 {{1}必须分配大小为 50000 的 },如果您使用 std::vector,则元素访问复杂度为 O(log n) 而不是 O(1)。在这个问题中使用了 50001,它在平均情况下通过使用 std::set/std::map 提供 O(1) 恒定时间复杂度,而无需分配大空间。