std :: unordered_map如何处理冲突?

时间:2016-05-04 11:42:31

标签: c++ c++11 hashmap unordered-map

std::unordered_map保证O(1)时间搜索,但它如何管理冲突?

Cppreference声明

  

无序映射是一个关联容器,包含具有唯一键的键值对。元素的搜索,插入和删除具有平均的恒定时间复杂度。

假设所有哈希码都相同的情况,内部如何处理冲突?

如果哈希码对每个键都是唯一的,那么我的假设就完全错了。在这种情况下,如何在没有冲突的情况下创建唯一的哈希码?

std::unordered_map的哈希函数采用什么方法来保证O(1)搜索?

3 个答案:

答案 0 :(得分:7)

它不保证O(1),它平均为O(1)...最坏的情况是,当存在大量碰撞时它可以是O(n)。请参阅以下链接,了解更多信息:

https://stackoverflow.com/a/2771398/5874704

<强>更新

由于问题已被编辑,现在专门询问std::unordered_map的冲突,请查看以下答案:

https://stackoverflow.com/a/21519560/5874704

  

我认为我们可以得出结论,std :: unordered_set(或unordered_map)的所有实际实现几乎肯定都使用了碰撞链接。虽然可能(几乎不可能)使用线性探测或双重散列来满足要求,但这样的实现似乎失去了很多,并且几乎没有任何回报。

答案 1 :(得分:2)

您的帖子中遗漏了至关重要的理解:std::unordered_map 平均情况 O(1)搜索。地图中的元素数量最多可能需要O(n)来检索元素。

至于它使用的哈希函数 - 这取决于用户。默认情况下,它使用std::hash

关于碰撞处理的散列函数的唯一要求是

  

只需要在程序的单次执行中为相同的输入产生相同的结果;这允许盐渍哈希防止碰撞DoS攻击。 (cppreference)

答案 2 :(得分:1)

  

std :: unordered_map保证O(1)时间搜索,但它如何管理冲突?

它使用开放式寻址/单独链接,请参阅here

  

Cppreference声明

     

无序映射是一个关联容器,包含具有唯一键的键值对。元素的搜索,插入和删除具有平均的恒定时间复杂度。

     

假设所有哈希码都相同的情况,内部如何处理冲突?

将碰撞元素添加到另一个容器中,该容器包含散列到该存储桶的所有值。该容器通常是一个链表,但没有什么能阻止使用例如二叉树。

  

如果哈希码对每个键都是唯一的,那么我的假设就完全错了。在这种情况下,如何在没有冲突的情况下创建唯一的哈希码?

unordered_map不需要或预期会做任何特殊的事情来避免冲突。 (无论如何,“每个键都是唯一的哈希码”是不够的,因为当哈希码被屏蔽或修改为桶的数量时,可以创建冲突。)

  

std :: unordered_map的散列函数采用什么方法来保证O(1)搜索?

这是你误解的关键。当散列函数在存储桶中散列密钥时,unordered_map具有O(1)性能。如果散列函数较差,它可能会降级为O(n),或者被已知散列到同一存储桶的密钥的恶意输入故意作为目标。标准不要求实现来防止这种情况发生,但是用户可以提供加密哈希,在运行时从一个系列中选择一个哈希函数,或者使恶意用户(或者通常类似的输入)不可能产生更多的冲突。< / p>