std::unordered_map如何处理冲突

How does std::unordered_map handle collisions?

本文关键字:处理 冲突 unordered map std 何处理      更新时间:2023-10-16

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

Cppreference声称

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

假设所有哈希码都相同,那么如何在内部处理冲突?

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

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

它不保证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)的所有实际实现几乎肯定都使用了冲突链接。虽然使用线性探测或双重哈希可能(只是几乎不可能)满足要求,但这样的实现似乎损失很大,几乎没有任何回报。

您的帖子中有一个遗漏,这对理解至关重要:std::unordered_map具有平均情况O(1)搜索。检索元素可能需要映射中元素数量中的O(n)

至于它使用哪个散列函数,这取决于用户。默认情况下,它使用std::hash

关于冲突处理,散列函数的唯一要求是

散列函数只需要在一个程序的单个执行中为相同的输入产生相同的结果;这允许使用盐散列来防止碰撞DoS攻击。(cppreference)

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

它使用开放寻址/单独链接,请参阅此处。

Cppreference声称

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

假设所有哈希码都相同,那么如何在内部处理冲突?

冲突的元素被添加到另一个容器中,该容器包含散列到该bucket的所有值。该容器通常是一个链表,但没有什么可以阻止使用例如二进制树的实现。

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

unordered_map不需要也不期望做任何特殊的事情来避免冲突。(散列码"每个密钥唯一"无论如何都是不够的,因为当散列码被屏蔽或模化成桶的数量时,可能会产生冲突。)

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

这是你误解的症结所在。当散列函数在存储桶之间对密钥进行适当的散列时,unordered_map具有O(1)性能。如果散列函数很差,或者被已知散列到同一存储桶的密钥的恶意输入故意作为目标,则它可能降级为O(n)。该标准不要求实现来防止这种情况,但用户可以提供加密哈希,在运行时从族中选择哈希函数,或者以其他方式使恶意用户(或通常类似的输入)无法创建更多冲突。