hash_map是个很有用的索引结构,对于大规模数据检索的时候,用处大大的。本文基于源码的基础上,从数据结构开始剖析,进而介绍一些常用的方法。hash_map是基于hash_table基础上封装的方法类,下面看看hash_table的数据结构:
template<class _Key, class _Tp, class _HashFn = hash<_Key>,
class _EqualKey = equal_to<_Key>, class _Alloc = allocator<_Tp> >
class hash_map
{
private:
typedef hashtable<pair<const _Key, _Tp>,_Key, _HashFn,
_Select1st<pair<const _Key, _Tp> >,
_EqualKey, _Alloc> _Ht;
_Ht _M_ht;
}//hash_map 类的部分定义
//下面是hashtable的数据结构定义
template<class _Val>
struct _Hashtable_node
{
_Hashtable_node* _M_next;
_Val _M_val;
};//节点类
template<class _Val, class _Key, class _HashFcn,
class _ExtractKey, class _EqualKey, class _Alloc>
class hashtable
{
typedef _Hashtable_node<_Val> _Node;
typedef vector<_Node*, _Nodeptr_Alloc> _Vector_type;
_Vector_type _M_buckets;
}
从上面可以看出:
hashtable的主要数据结构是个vector, 里面的元素是_Hashtable_node节点类型(链表的结构),并且此节点的value是个pair<key, value>类型。
结构图如下:
一些方法解析:
插入:
pair<iterator, bool>
insert_unique(const value_type& __obj)
{
resize(_M_num_elements + 1);//重置hash_table的空间,有一张表__stl_prime_list,按照这张表进行动态的扩展空间。
//每扩展一次,都重新开辟一个大点的空间,再重新hash,并把老的hash表拷贝过来。
return insert_unique_noresize(__obj);//插入一个值(key, value)
}
template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
pair<typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator, bool>
hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
insert_unique_noresize(const value_type& __obj)
{
const size_type __n = _M_bkt_num(__obj);//使用hash(key)%n 得到hashtable的位置
_Node* __first = _M_buckets[__n];//使用节点指针,指向hashtable的指定位置
for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)//判断是否有相等的key,有则返回相同key的节点指针。
if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
return pair<iterator, bool>(iterator(__cur, this), false);
_Node* __tmp = _M_new_node(__obj);//插入操作
__tmp->_M_next = __first;
_M_buckets[__n] = __tmp;
++_M_num_elements;
return pair<iterator, bool>(iterator(__tmp, this), true);
}
参考文章:
详细解说hash_map http://blog.sina.com.cn/s/blog_4c98b9600100audq.html