std::unordered_map
保证O(1)时间搜索,但它如何管理冲突?
无序映射是一个关联容器,包含具有唯一键的键值对。元素的搜索,插入和删除具有平均的恒定时间复杂度。
假设所有哈希码都相同的情况,内部如何处理冲突?
如果哈希码对每个键都是唯一的,那么我的假设就完全错了。在这种情况下,如何在没有冲突的情况下创建唯一的哈希码?
std::unordered_map
的哈希函数采用什么方法来保证O(1)搜索?
答案 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>