繁体   English   中英

std::unordered_map 如何确定 hash 表中特定键的位置?

[英]How does std::unordered_map determine the location of a specific key in a hash table?

文档提到std::unordered_map使用 hash 表。 它如何实现对 hash 表中特定键的 O(1) 查找? 我能想到的唯一方法是将每个键存储在根据它所保存的数据的 hash 值计算的地址中。 如果是这种情况,它如何将 memory 中的所有键保持在一起,以免很快用完? 此外,如果使用了多个std::unordered_map怎么办? 实现如何保证没有两个映射会计算归结为相同地址的哈希?

O(1)并不意味着算法的复杂性是“一次”,或者在这种情况下,map 中的值必须通过某种基于其键的单一查找来检索。

O(1)真正的意思是O(amortized constant) ,也就是说:平均而言,它需要一个恒定的时间来完成。

One possible implementation for an unordered map would be a hash table containing a linked list of all values that have the same hash key, and the unordered map dynamically adjusts the size of the hash table, as needed. 完全有可能偶尔的 map 查找将不得不搜索一个小的链表来找到正确的 hash 键。 此外,有时,插入或删除操作会花费额外的时间来重新散列整个无序 map。

如果您在参考资料中查找无序映射方法的详细信息,您会发现它明确提到,如果修改触发重新散列,无序 map 的所有存在都会失效。

但是,平均而言,无序的 map 查找预计需要固定的时间。

通常,hash map 会在内部保留一系列存储桶。 另一方面,存储桶是条目列表。 像这样的东西:

template<class TKey, class TValue>
class HashMap {
    vector<vector<pair<TKey, TValue>>> Buckets;
};

然后,当您进行查找时,它只需获取密钥,计算其 hash,例如hash ,转到Buckets[hash % Buckets.size] ,它的类型为vector<pair<TKey,TValue>>并进行线性搜索它。 这使得摊销(平均)查找复杂度保持不变,而在最坏的情况下(例如,糟糕的散列函数)它是线性的。 事实上,这是您使用 unordered_map 获得的保证。

请注意,当您添加元素时(甚至可能在您删除元素时),顶层向量最终会增长,以允许更多条目并避免冲突。 在这种情况下,可能会发生重新散列。 因此添加/删除元素并非易事,而且有时可能会很昂贵。

另请注意,由于vector在底层堆上分配 memory,因此使用多个 map 没有问题。 他们什么都不分享(好吧,他们可能会分享一些东西,但这不会影响行为)。 但即使实现不使用vector (这不是强制性的,它只是一个示例),也必须使用某种形式的动态malloc来保证这一点。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM