STL 容器 -- unordered_map/set
7、unordered_map/unordered_set/unordered_multimap/unordered_multiset(C++11)
STL 这四个容器底层实现都是哈希表,因为哈希表不具备排序功能,所以这四个容器元素都是无序的。底层哈希表整体布局如下:
如果想进一步了解哈希表,可以查阅分析的文章
7.1、unordered_map
unordered_map 和 map 除了底层实现不同,其他接口类似。
unordered_map 只有一个成员变量 _M_h,是 __umap_hashtable 类型。__umap_hashtable 就是 GCC 哈希表实现 _Hashtable 的别名,使用的是 _Prime_rehash_policy 扩容策略。
_Hashtable 的数据域保存的是 pair<Key, Value> 类型。
/// unordered_map.h template<bool _Cache> using __umap_traits = __detail::_Hashtable_traits<_Cache, false, true>; template<typename _Key, typename _Tp, typename _Hash = hash<_Key>, typename _Pred = std::equal_to<_Key>, typename _Alloc = std::allocator<std::pair<const _Key, _Tp> >, typename _Tr = __umap_traits<__cache_default<_Key, _Hash>::value>> using __umap_hashtable = _Hashtable<_Key, std::pair<const _Key, _Tp>, _Alloc, __detail::_Select1st, _Pred, _Hash, __detail::_Mod_range_hashing, __detail::_Default_ranged_hash, __detail::_Prime_rehash_policy, _Tr>; 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_traits 最后一个表示是否元素唯一,unordered_map 指定的模板参数是 true,表示元素唯一。
/// hashtable_policy.h template<bool _Cache_hash_code, bool _Constant_iterators, bool _Unique_keys> struct _Hashtable_traits { using __hash_cached = __bool_constant<_Cache_hash_code>; using __constant_iterators = __bool_constant<_Constant_iterators>; using __unique_keys = __bool_constant<_Unique_keys>; };
插入和删除调用 _Hashtable 的实现。
/// unordered_map.h std::pair<iterator, bool> insert(const value_type& __x) { return _M_h.insert(__x); } iterator erase(const_iterator __position) { return _M_h.erase(__position); }
_Hashtable 的 max_load_factor 是可以被修改,并且是使用过程中可以修改。
/// unordered_map.h void max_load_factor(float __z) { _M_h.max_load_factor(__z); }
7.2、unordered_set
unordered_set 和 unorsered_map 实现完全一致,只不过 _Hashtable 节点数据域保存的是 value,而不是想 unordered_map 保存的是 pair<Key, Value> 键值对。
/// unordered_set.h template<bool _Cache> using __uset_traits = __detail::_Hashtable_traits<_Cache, true, true>; template<typename _Value, typename _Hash = hash<_Value>, typename _Pred = std::equal_to<_Value>, typename _Alloc = std::allocator<_Value>, typename _Tr = __uset_traits<__cache_default<_Value, _Hash>::value>> using __uset_hashtable = _Hashtable<_Value, _Value, _Alloc, __detail::_Identity, _Pred, _Hash, __detail::_Mod_range_hashing, __detail::_Default_ranged_hash, __detail::_Prime_rehash_policy, _Tr>; template<typename _Value, typename _Hash = hash<_Value>, typename _Pred = equal_to<_Value>, typename _Alloc = allocator<_Value>> class unordered_set { typedef __uset_hashtable<_Value, _Hash, _Pred, _Alloc> _Hashtable; _Hashtable _M_h; /* ... */ };
7.3、unordered_multimap
unordered_multimap 和 unordered_map 相似。两者的区别是使用了不同的 _Hashtable_traits。
/// unordered_map.h template<bool _Cache> using __ummap_traits = __detail::_Hashtable_traits<_Cache, false, false>; template<typename _Key, typename _Tp, typename _Hash = hash<_Key>, typename _Pred = std::equal_to<_Key>, typename _Alloc = std::allocator<std::pair<const _Key, _Tp> >, typename _Tr = __ummap_traits<__cache_default<_Key, _Hash>::value>> using __ummap_hashtable = _Hashtable<_Key, std::pair<const _Key, _Tp>, _Alloc, __detail::_Select1st, _Pred, _Hash, __detail::_Mod_range_hashing, __detail::_Default_ranged_hash, __detail::_Prime_rehash_policy, _Tr>; template<typename _Key, typename _Tp, typename _Hash = hash<_Key>, typename _Pred = equal_to<_Key>, typename _Alloc = allocator<std::pair<const _Key, _Tp>>> class unordered_multimap { typedef __ummap_hashtable<_Key, _Tp, _Hash, _Pred, _Alloc> _Hashtable; _Hashtable _M_h; /* ... */ };
_Hashtable_traits 最后一个表示是否元素唯一,unordermap_multimap 模板参数是 false,要求 _Hashtable 中元素不唯一。
7.4、unordered_multiset
unordered_multiset 和 unordered_multimap 实现一致,只不过 _Hashtable 节点数据域保存的是 Value,而 unordered_map 保存的是 pair<Key, Value> 键值对。
/// unordered_set.h template<bool _Cache> using __umset_traits = __detail::_Hashtable_traits<_Cache, true, false>; template<typename _Value, typename _Hash = hash<_Value>, typename _Pred = std::equal_to<_Value>, typename _Alloc = std::allocator<_Value>, typename _Tr = __umset_traits<__cache_default<_Value, _Hash>::value>> using __umset_hashtable = _Hashtable<_Value, _Value, _Alloc, __detail::_Identity, _Pred, _Hash, __detail::_Mod_range_hashing, __detail::_Default_ranged_hash, __detail::_Prime_rehash_policy, _Tr>; template<typename _Value, typename _Hash = hash<_Value>, typename _Pred = equal_to<_Value>, typename _Alloc = allocator<_Value>> class unordered_multiset { typedef __umset_hashtable<_Value, _Hash, _Pred, _Alloc> _Hashtable; _Hashtable _M_h; /* ... */ };
欢迎关注公众号“源知源为”,阅读更多技术干货
#23届找工作求助阵地##C++#C/C++ 语言基础