【问题标题】:Confused about C++ unordered_map and hash collision对 C++ unordered_map 和哈希冲突感到困惑
【发布时间】:2015-06-29 17:45:21
【问题描述】:

我读过 unordered_map 将具有相同哈希的元素放在桶中,这就是它处理哈希冲突的方式。但是,当我检查insert function 时,它说:

每个元素只有在其键不等于容器中任何其他元素的键时才会插入

这是否意味着我不能插入具有相同散列的元素?.. 我应该能够插入具有新散列的元素,因为 unordered_map 结构可以处理冲突,对吧?.. 我想我可以错过了什么。

【问题讨论】:

  • 2个不同的key可以产生同一个hash,甚至2个不同的hash也可以对应同一个bucket。

标签: c++ c++11 hash hashtable unordered-map


【解决方案1】:

当您意识到散列不一定是关键时,这些语句肯定可能保持一致。

一组不同的键可能会生成相同的哈希值,因此存储在同一个桶中,但这仍然允许限制重复键是不允许的。

例如,假设您有一个使用名字作为键的friends 集合。哈希函数是(相当简单的)“使用名称的第一个字母。

因此,虽然 Albert、Andrew、Adam、Bill、Benny 和 Chloe 是六个不同的键,它们只占三个不同的哈希值:

          A                 B            C    (buckets)
   ______/|\_____          / \           |
  /       |      \        /   \          |
Albert  Andrew  Adam    Bill  Benny    Chloe  (keys)

【讨论】:

  • 值得一提的是,2 个不同的哈希值最终可能会出现在同一个存储桶中,因为(几乎可以肯定)可能的哈希值会比存储桶多得多。
  • @BoBTFish,我猜这取决于你如何定义哈希。如果你得到一个 32 位“散列”,它被进一步简化为一个 8 位存储桶 ID,我倾向于不将 32 位值称为散列,而是一个中间值。真正的哈希是存储桶 ID。
  • 对我来说,它是hasherresult_type。 “bucket id”必须与bucket_countmax_bucket_count返回的类型相同,即size_type
  • @BoBTFish,我认为这只是一个术语问题。哈希函数的整个 point 是将数据有效地转换为存储桶 ID,一旦您拥有该存储桶 ID,中间“哈希”值几乎没有用处。您似乎在说hash = hashFn(data); bucket = hash % 200; 之类的东西,而我更多地将其视为hashAndBucket = hashFn(data) % 200;(或散列函数本身将中间值减少为存储桶ID)。
  • @paxdiablo:在哈希表中使用只是哈希函数输出的一种应用——它们也可以用于例如作为校验和,作为密钥,作为最近密码的固定大小的统计不完美但良好的不可逆转记录,在设置另一个密码时是不允许的等等。在映射到存储桶后区分从冲突中获取相同的哈希函数输出也很有用,所以你知道是否需要更好的散列函数,或者更低的负载因子,或者自定义的非标准库散列表可能从 2 的幂的桶计数移动到素数....
猜你喜欢
  • 2010-10-19
  • 2017-04-26
  • 2016-03-14
  • 2016-10-04
  • 2016-05-03
  • 2016-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多