根据按键类型选择地图或unordered_map

Selection of map or unordered_map based on keys's type

本文关键字:地图 unordered map 选择地 选择 类型      更新时间:2023-10-16

一个普遍询问的问题是,我们是否应该使用unordered_map或地图以更快地访问。这个问题的最常见(相当古老)的答案是:如果您想直接访问单个元素,请使用unordered_map,但是如果要迭代元素(最有可能以分类方式)使用地图。

在做出这样的选择时,我们不应该考虑键的数据类型吗?作为一种数据类型(例如int)的哈希算法可能比其他(例如字符串)更容易碰撞。

如果是这种情况(哈希算法很容易碰撞),那么我可能会使用映射即可直接访问,例如o(1)o(1)恒定时间(可能在输入的大型输入中平均)unordered_map映射即使对于n。

的相当大的价值,也要超过lg(n)

您提出了一个很好的观点...但是您专注于错误的部分。

问题本身不是键的类型,而是用于推导该键的哈希值的哈希函数。

词典订购是 easy :如果您告诉我您想根据其3个字段订购结构(他们已经支持订购自己),那么我只写信:

bool operator<(Struct const& left, Struct const& right) {
    return boost::tie(left._1,  left._2,  left._3)
         < boost::tie(right._1, right._2, right._3);
}

我完成了!

但是编写哈希函数是困难。您需要一些有关数据分布(统计)的知识,您可能需要防止专门制作的攻击等...老实说,我希望很多人都能能够制作出良好的哈希功能。但是最糟糕的部分是,构图也很难!给定两个独立字段,将其哈希值组合很难(提示: boost::hash_combine)。

因此,确实,如果您不知道自己在做什么,并且正在处理用户制作的数据,那就坚持使用map。也许较慢(不确定),但是更安全。

实际上并没有像碰撞易于对象那样的东西,因为此东西取决于您使用的哈希函数。假设对象不完全相同 - 可以使用一些功能来创建一个有益的哈希函数。

假设您对数据有一些知识 - 并且您知道某些哈希函数h1()可能会有很多碰撞 - 那么您应该找到并使用不同的哈希函数h2(),这更适合此任务。/p>


也就是说,还有其他问题以及为什么基于树的数据结构而不是哈希基础(例如延迟和集合的大小),我的答案在此线程中涵盖了一些。

毫无意义地试图对此太聪明。与往常一样,配置文件,比较,优化如果有用。涉及许多因素 - 标准中未指定的很多因素,并且会因编译器而异。有些事情可能会在特定的硬件上更好或更糟。如果您对这些东西感兴趣(或付费假装为),则应该更加系统地了解这些东西。您可能首先要学习一些有关实际哈希功能及其特征的知识。找不到所有实际目的的哈希函数非常罕见,没有比随机但可重复的值更碰撞的倾斜度 - 有时候,接近这一点的次数比处理一些额外的碰撞要慢。