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