本次来讲解下c++中 std::unordered_map
的设计原理。
std::unordered_map
里面has-a
哈希表,它提供的的各个方法基本都是由hashtable封装实现,因此在下文使用hashtable
来描述std::unordered_map
。
// gnu 实现
template<typename _Key,
typename _Tp,
typename _Hash = hash<_Key>,
typename _Pred = equal_to<_Key>,
typename _Alloc = allocator<std::pair<const _Key, _Tp>>>
class unordered_map
{
typedef __umap_hashtable<_Key, _Tp, _Hash, _Pred, _Alloc> _Hashtable;
_Hashtable _M_h; // 内部的唯一成员变量: hashtable
//...
}
O(1)
数组,可以通过索引index
在O(1)的时间复杂度内获取元素,但如果不知道index则要O(N)
的时间复杂度来查找该节点。hashtable
为了弥补这一缺点,采用一个hash函数来计算元素的索引值,来满足O(1)的搜索时间复杂度。其过程如下。
- 计算元素的哈希值。对于单个键值对
{key, value}
,计算key对应的哈希值hashcode = hash_func(key)
。 - 计算元素在数组中的索引值。由于hashcode不一定处于
[0, bucket_count]
范围内,因此需要将hashcode映射到该范围:index = hashcode % bucket_count
。
上面两步以O(1)时间复杂度获取了元素在数组中的索引值index
,进一步,则能以O(1)时间复杂度给该索引位置赋值或者获取该索引位置的值。两个步骤可实现如下:
size_t bucket_index(const std::unordered_map<int, int>& map, int key) {
size_t bucket_count = map.bucket_count(); // map 的桶的个数
const