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>
struct _Hashtable_iterator {typedef hashtable<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>_Hashtable;typedef _Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>iterator;typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>const_iterator;typedef _Hashtable_node<_Val> _Node;typedef forward_iterator_tag iterator_category;typedef _Val value_type;typedef ptrdiff_t difference_type;typedef size_t size_type;typedef _Val& reference;typedef _Val* pointer;_Node* _M_cur; //迭代器目前所指节点_Hashtable* _M_ht;//保持对容器的连结关系(因为可能需要从bucket跳到bucket)_Hashtable_iterator(_Node* __n, _Hashtable* __tab) : _M_cur(__n), _M_ht(__tab) {}_Hashtable_iterator() {}reference operator*() const { return _M_cur->_M_val; }
#ifndef __SGI_STL_NO_ARROW_OPERATORpointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */iterator& operator++();iterator operator++(int);bool operator==(const iterator& __it) const{ return _M_cur == __it._M_cur; }bool operator!=(const iterator& __it) const{ return _M_cur != __it._M_cur; }
};
template <class _Val, class _Key, class _HF, class _ExK, class _EqK, class _All>
_Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&
_Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++()
{const _Node* __old = _M_cur;_M_cur = _M_cur->_M_next; //如果存在,就是它,否则进入ifif (!_M_cur) {//根据元素值,定位出下一个bucket。其起头处就是我们的目的地size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())//注意operator++_M_cur = _M_ht->_M_buckets[__bucket];}return *this;
}template <class _Val, class _Key, class _HF, class _ExK, class _EqK, class _All>
inline _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>
_Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++(int)
{iterator __tmp = *this;++*this; //调用operator++()return __tmp;
}
template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
class hashtable;template <class _Val, class _Key, class _HashFcn,class _ExtractKey, class _EqualKey, class _Alloc>
class hashtable {
public:typedef _Key key_type;typedef _Val value_type;typedef _HashFcn hasher; //为template类型参数重新定义一个名字typedef _EqualKey key_equal;//为template类型参数重新定义一个名字typedef size_t size_type;typedef ptrdiff_t difference_type;typedef value_type* pointer;typedef const value_type* const_pointer;typedef value_type& reference;typedef const value_type& const_reference;hasher hash_funct() const { return _M_hash; }key_equal key_eq() const { return _M_equals; }private:typedef _Hashtable_node<_Val> _Node;#ifdef __STL_USE_STD_ALLOCATORS
public:typedef typename _Alloc_traits<_Val,_Alloc>::allocator_type allocator_type;allocator_type get_allocator() const { return _M_node_allocator; }
private:typename _Alloc_traits<_Node, _Alloc>::allocator_type _M_node_allocator;_Node* _M_get_node() { return _M_node_allocator.allocate(1); }void _M_put_node(_Node* __p) { _M_node_allocator.deallocate(__p, 1); }
# define __HASH_ALLOC_INIT(__a) _M_node_allocator(__a),
#else /* __STL_USE_STD_ALLOCATORS */
public:typedef _Alloc allocator_type;allocator_type get_allocator() const { return allocator_type(); }
private:typedef simple_alloc<_Node, _Alloc> _M_node_allocator_type;_Node* _M_get_node() { return _M_node_allocator_type::allocate(1); }void _M_put_node(_Node* __p) { _M_node_allocator_type::deallocate(__p, 1); }
# define __HASH_ALLOC_INIT(__a)
#endif /* __STL_USE_STD_ALLOCATORS */private:hasher _M_hash;key_equal _M_equals;_ExtractKey _M_get_key;vector<_Node*,_Alloc> _M_buckets; //哈希表以vector实现size_type _M_num_elements;public:typedef _Hashtable_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>iterator;typedef _Hashtable_const_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>const_iterator;friend struct_Hashtable_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>;friend struct_Hashtable_const_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>;public:hashtable(size_type __n,const _HashFcn& __hf,const _EqualKey& __eql,const _ExtractKey& __ext,const allocator_type& __a = allocator_type()): __HASH_ALLOC_INIT(__a)_M_hash(__hf),_M_equals(__eql),_M_get_key(__ext),_M_buckets(__a),_M_num_elements(0){_M_initialize_buckets(__n);}hashtable(size_type __n,const _HashFcn& __hf,const _EqualKey& __eql,const allocator_type& __a = allocator_type()): __HASH_ALLOC_INIT(__a)_M_hash(__hf),_M_equals(__eql),_M_get_key(_ExtractKey()),_M_buckets(__a),_M_num_elements(0){_M_initialize_buckets(__n);}hashtable(const hashtable& __ht): __HASH_ALLOC_INIT(__ht.get_allocator())_M_hash(__ht._M_hash),_M_equals(__ht._M_equals),_M_get_key(__ht._M_get_key),_M_buckets(__ht.get_allocator()),_M_num_elements(0){_M_copy_from(__ht);}#undef __HASH_ALLOC_INIThashtable& operator= (const hashtable& __ht){if (&__ht != this) {clear();_M_hash = __ht._M_hash;_M_equals = __ht._M_equals;_M_get_key = __ht._M_get_key;_M_copy_from(__ht);}return *this;}~hashtable() { clear(); }size_type size() const { return _M_num_elements; }size_type max_size() const { return size_type(-1); }bool empty() const { return size() == 0; }void swap(hashtable& __ht){__STD::swap(_M_hash, __ht._M_hash);__STD::swap(_M_equals, __ht._M_equals);__STD::swap(_M_get_key, __ht._M_get_key);_M_buckets.swap(__ht._M_buckets);__STD::swap(_M_num_elements, __ht._M_num_elements);}iterator begin(){ for (size_type __n = 0; __n < _M_buckets.size(); ++__n)if (_M_buckets[__n])return iterator(_M_buckets[__n], this);return end();}iterator end() { return iterator(0, this); }const_iterator begin() const{for (size_type __n = 0; __n < _M_buckets.size(); ++__n)if (_M_buckets[__n])return const_iterator(_M_buckets[__n], this);return end();}const_iterator end() const { return const_iterator(0, this); }#ifdef __STL_MEMBER_TEMPLATEStemplate <class _Vl, class _Ky, class _HF, class _Ex, class _Eq, class _Al>friend bool operator== (const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&,const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&);
#else /* __STL_MEMBER_TEMPLATES */friend bool __STD_QUALIFIERoperator== __STL_NULL_TMPL_ARGS (const hashtable&, const hashtable&);
#endif /* __STL_MEMBER_TEMPLATES */public://返回vector的大小size_type bucket_count() const { return _M_buckets.size(); }size_type max_bucket_count() const{ return __stl_prime_list[(int)__stl_num_primes - 1]; } size_type elems_in_bucket(size_type __bucket) const{size_type __result = 0;for (_Node* __cur = _M_buckets[__bucket]; __cur; __cur = __cur->_M_next)__result += 1;return __result;}pair<iterator, bool> insert_unique(const value_type& __obj){resize(_M_num_elements + 1);return insert_unique_noresize(__obj);}iterator insert_equal(const value_type& __obj){resize(_M_num_elements + 1);return insert_equal_noresize(__obj);}pair<iterator, bool> insert_unique_noresize(const value_type& __obj);iterator insert_equal_noresize(const value_type& __obj);#ifdef __STL_MEMBER_TEMPLATEStemplate <class _InputIterator>void insert_unique(_InputIterator __f, _InputIterator __l){insert_unique(__f, __l, __ITERATOR_CATEGORY(__f));}template <class _InputIterator>void insert_equal(_InputIterator __f, _InputIterator __l){insert_equal(__f, __l, __ITERATOR_CATEGORY(__f));}template <class _InputIterator>void insert_unique(_InputIterator __f, _InputIterator __l,input_iterator_tag){for ( ; __f != __l; ++__f)insert_unique(*__f);}template <class _InputIterator>void insert_equal(_InputIterator __f, _InputIterator __l,input_iterator_tag){for ( ; __f != __l; ++__f)insert_equal(*__f);}template <class _ForwardIterator>void insert_unique(_ForwardIterator __f, _ForwardIterator __l,forward_iterator_tag){size_type __n = 0;distance(__f, __l, __n);resize(_M_num_elements + __n);for ( ; __n > 0; --__n, ++__f)insert_unique_noresize(*__f);}template <class _ForwardIterator>void insert_equal(_ForwardIterator __f, _ForwardIterator __l,forward_iterator_tag){size_type __n = 0;distance(__f, __l, __n);resize(_M_num_elements + __n);for ( ; __n > 0; --__n, ++__f)insert_equal_noresize(*__f);}#else /* __STL_MEMBER_TEMPLATES */void insert_unique(const value_type* __f, const value_type* __l){size_type __n = __l - __f;resize(_M_num_elements + __n);for ( ; __n > 0; --__n, ++__f)insert_unique_noresize(*__f);}void insert_equal(const value_type* __f, const value_type* __l){size_type __n = __l - __f;resize(_M_num_elements + __n);for ( ; __n > 0; --__n, ++__f)insert_equal_noresize(*__f);}void insert_unique(const_iterator __f, const_iterator __l){size_type __n = 0;distance(__f, __l, __n);resize(_M_num_elements + __n);for ( ; __n > 0; --__n, ++__f)insert_unique_noresize(*__f);}void insert_equal(const_iterator __f, const_iterator __l){size_type __n = 0;distance(__f, __l, __n);resize(_M_num_elements + __n);for ( ; __n > 0; --__n, ++__f)insert_equal_noresize(*__f);}
#endif /*__STL_MEMBER_TEMPLATES */reference find_or_insert(const value_type& __obj);iterator find(const key_type& __key) {size_type __n = _M_bkt_num_key(__key);_Node* __first;for ( __first = _M_buckets[__n];__first && !_M_equals(_M_get_key(__first->_M_val), __key);__first = __first->_M_next){}return iterator(__first, this);} const_iterator find(const key_type& __key) const{size_type __n = _M_bkt_num_key(__key);const _Node* __first;for ( __first = _M_buckets[__n];__first && !_M_equals(_M_get_key(__first->_M_val), __key);__first = __first->_M_next){}return const_iterator(__first, this);} size_type count(const key_type& __key) const{const size_type __n = _M_bkt_num_key(__key);size_type __result = 0;for (const _Node* __cur = _M_buckets[__n]; __cur; __cur = __cur->_M_next)if (_M_equals(_M_get_key(__cur->_M_val), __key))++__result;return __result;}pair<iterator, iterator> equal_range(const key_type& __key);pair<const_iterator, const_iterator> equal_range(const key_type& __key) const;size_type erase(const key_type& __key);void erase(const iterator& __it);void erase(iterator __first, iterator __last);void erase(const const_iterator& __it);void erase(const_iterator __first, const_iterator __last);void resize(size_type __num_elements_hint);void clear();private:size_type _M_next_size(size_type __n) const{ return __stl_next_prime(__n); }void _M_initialize_buckets(size_type __n){const size_type __n_buckets = _M_next_size(__n);_serve(__n_buckets);_M_buckets.insert(_d(), __n_buckets, (_Node*) 0);_M_num_elements = 0;}size_type _M_bkt_num_key(const key_type& __key) const{return _M_bkt_num_key(__key, _M_buckets.size());}size_type _M_bkt_num(const value_type& __obj) const{return _M_bkt_num_key(_M_get_key(__obj));}size_type _M_bkt_num_key(const key_type& __key, size_t __n) const{return _M_hash(__key) % __n;}size_type _M_bkt_num(const value_type& __obj, size_t __n) const{return _M_bkt_num_key(_M_get_key(__obj), __n);}_Node* _M_new_node(const value_type& __obj){_Node* __n = _M_get_node();__n->_M_next = 0;__STL_TRY {construct(&__n->_M_val, __obj);return __n;}__STL_UNWIND(_M_put_node(__n));}void _M_delete_node(_Node* __n){destroy(&__n->_M_val);_M_put_node(__n);}void _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last);void _M_erase_bucket(const size_type __n, _Node* __last);void _M_copy_from(const hashtable& __ht);};
//下面的都是全局枚举与全局函数//假设long至少有32bits
enum { __stl_num_primes = 28 };static const unsigned long __stl_prime_list[__stl_num_primes] =
{53ul, 97ul, 193ul, 389ul, 769ul,1543ul, 3079ul, 6151ul, 12289ul, 24593ul,49157ul, 98317ul, 196613ul, 393241ul, 786433ul,1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul, 1610612741ul, 3221225473ul, 4294967291ul
};//以下找出上述28个质数之中,最接近并大于n的那个质数
inline unsigned long __stl_next_prime(unsigned long __n)
{const unsigned long* __first = __stl_prime_list;const unsigned long* __last = __stl_prime_list + (int)__stl_num_primes;const unsigned long* pos = lower_bound(__first, __last, __n);//以上lower_bound()是泛型算法//使用lower_bound(),序列需先排序return pos == __last ? *(__last - 1) : *pos;
}
template <class _Val, class _Key, class _HashFcn,class _ExtractKey, class _EqualKey, class _Alloc>
class hashtable {
//...
public://总共可以有多少bucketssize_type max_bucket_count() const{ return __stl_prime_list[(int)__stl_num_primes - 1]; }
//...
};
template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
class hashtable;template <class _Val, class _Key, class _HashFcn,class _ExtractKey, class _EqualKey, class _Alloc>
class hashtable {
//...
private:typedef simple_alloc<_Node, _Alloc> _M_node_allocator_type;
//...
};
_Node* _M_new_node(const value_type& __obj)
{_Node* __n = _M_get_node();__n->_M_next = 0;__STL_TRY {construct(&__n->_M_val, __obj);return __n;}__STL_UNWIND(_M_put_node(__n));
}void _M_delete_node(_Node* __n)
{destroy(&__n->_M_val);_M_put_node(__n);
}void _M_put_node(_Node* __p) { _M_node_allocator.deallocate(__p, 1); }
template <class _Val, class _Key, class _HashFcn,class _ExtractKey, class _EqualKey, class _Alloc>
class hashtable {
public:hashtable(size_type __n,const _HashFcn& __hf,const _EqualKey& __eql,const _ExtractKey& __ext,const allocator_type& __a = allocator_type()): __HASH_ALLOC_INIT(__a)_M_hash(__hf),_M_equals(__eql),_M_get_key(__ext),_M_buckets(__a),_M_num_elements(0){_M_initialize_buckets(__n);}
private:void _M_initialize_buckets(size_type __n){const size_type __n_buckets = _M_next_size(__n);//调用_M_next_size//举例:传入50,返回53.以下首先保留53个元素空间,然后将其全部填0_serve(__n_buckets);_M_buckets.insert(_d(), __n_buckets, (_Node*) 0);_M_num_elements = 0;}//该函数返回最近接n并大于n的质数。其中调用了我们上面介绍的__stl_next_prime函数size_type _M_next_size(size_type __n) const{ return __stl_next_prime(__n); }
};
hashtable<int,int,hash<iny>,identity<int>,equal_to<int>,alloc> iht(50,hash<int>(),equal_to<int>());std::cout<<iht.size()<<std::endl; //0
std::cout<<iht.bucket_count()<<std::endl; //53。STL提供的第一个质数
pair<iterator, bool> insert_unique(const value_type& __obj)
{resize(_M_num_elements + 1); //判断是否需要重建表格return insert_unique_noresize(__obj); //在不需要重建表格的情况下插入节点,键值不允许重复
}
//以下函数判断是否需要重建表格。不需要就返回
template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::resize(size_type __num_elements_hint)
{//下面是否重建表格的判断原则很奇怪,是拿元素个数(把新增元素计入后)和bucket vector的大小来比较//如果前者大于后者,就重建表格//由此可知,每个bucket(list)的最大容量和buckets vector的大小相同const size_type __old_n = _M_buckets.size();if (__num_elements_hint > __old_n) { //确定真的需要重新配置const size_type __n = _M_next_size(__num_elements_hint);//找出下一个质数if (__n > __old_n) {vector<_Node*, _All> __tmp(__n, (_Node*)(0),__allocator()); //建立新的buckets__STL_TRY {//以下处理每一个旧的bucketfor (size_type __bucket = 0; __bucket < __old_n; ++__bucket) {_Node* __first = _M_buckets[__bucket];while (__first) {size_type __new_bucket = _M_bkt_num(__first->_M_val, __n);_M_buckets[__bucket] = __first->_M_next;__first->_M_next = __tmp[__new_bucket];__tmp[__new_bucket] = __first;__first = _M_buckets[__bucket]; }}_M_buckets.swap(__tmp);}
# ifdef __STL_USE_EXCEPTIONScatch(...) {for (size_type __bucket = 0; __bucket < __tmp.size(); ++__bucket) {while (__tmp[__bucket]) {_Node* __next = __tmp[__bucket]->_M_next;_M_delete_node(__tmp[__bucket]);__tmp[__bucket] = __next;}}throw;}
# endif /* __STL_USE_EXCEPTIONS */}}
}
_M_buckets[__bucket] = __first->_M_next; //(1)令旧的bucket指向其所对应之链表的下一个节点
__first->_M_next = __tmp[__new_bucket]; //(2)(3)将当前节点插入到新bucket内,成为其对应链表的第一个节点
__tmp[__new_bucket] = __first; //(4)回到旧的bucket所指的待处理链表,准备处理下一个节点
//在不需要重建表格的情况下插入节点,键值不允许重复
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); //决定obj应位于#n bucket_Node* __first = _M_buckets[__n]; //令first指向bucket对应之串行头部//如果buckets[n]已被占用,此时first将不为0,于是进入以下循环,走过bucket所对应的整个链表for (_Node* __cur = __first; __cur; __cur = __cur->_M_next) if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))//如果发现与链表中的某键值相同,就不插入,立即返回return pair<iterator, bool>(iterator(__cur, this), false);//离开循环(或根本不进入循环)时,first指向bucket所指链表的头结点_Node* __tmp = _M_new_node(__obj);__tmp->_M_next = __first;_M_buckets[__n] = __tmp; //令新节点称为链表的第一个节点++_M_num_elements; //节点个数累加1return pair<iterator, bool>(iterator(__tmp, this), true);
}
iterator insert_equal(const value_type& __obj)
{resize(_M_num_elements + 1); //在上面已介绍return insert_equal_noresize(__obj);
}
//在不需要重建表格的情况下插入新节点,键值允许重复
template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator
hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::insert_equal_noresize(const value_type& __obj)
{const size_type __n = _M_bkt_num(__obj);_Node* __first = _M_buckets[__n];for (_Node* __cur = __first; __cur; __cur = __cur->_M_next) if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) {_Node* __tmp = _M_new_node(__obj);__tmp->_M_next = __cur->_M_next;__cur->_M_next = __tmp;++_M_num_elements;return iterator(__tmp, this);}_Node* __tmp = _M_new_node(__obj);__tmp->_M_next = __first;_M_buckets[__n] = __tmp;++_M_num_elements;return iterator(__tmp, this);
}
//版本1:接受实值(value)和buckets个数
size_type _M_bkt_num(const value_type& __obj, size_t __n) const
{return _M_bkt_num_key(_M_get_key(__obj), __n); //调用版本4
}//版本2:只接受实值(value)
size_type _M_bkt_num(const value_type& __obj) const
{return _M_bkt_num_key(_M_get_key(__obj)); //调用版本3
}//版本3,只接受键值
size_type _M_bkt_num_key(const key_type& __key) const
{return _M_bkt_num_key(__key, _M_buckets.size()); //调用版本4
}//版本4:接受键值和buckets个数
size_type _M_bkt_num_key(const key_type& __key, size_t __n) const
{return _M_hash(__key) % __n; //SGI的所有内建的hash(),在后面的hash functions中介绍
}
template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::clear()
{//针对每一个bucketfor (size_type __i = 0; __i < _M_buckets.size(); ++__i) {_Node* __cur = _M_buckets[__i];//将bucket list中的每一个节点删除while (__cur != 0) {_Node* __next = __cur->_M_next;_M_delete_node(__cur);__cur = __next;}_M_buckets[__i] = 0; //令bucket内容为null指针}_M_num_elements = 0; //令总节点个数为0//注意,buckets vector并未释放迪奥空间,仍然保有原来大小
}
template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::_M_copy_from(const hashtable& __ht)
{_M_buckets.clear();//先清除自己的bucket vector//为自己的buvkets vector保留空间,使与对方相同//如果自己空间大于对方就不动。如果自己空间小于对方,就增大_serve(__ht._M_buckets.size());//从自己的buckets vector尾端开始,插入n个元素,其值为null//注意,此时buckets vector为空,所以所谓尾端,就是起头处_M_buckets.insert(_d(), __ht._M_buckets.size(), (_Node*) 0);__STL_TRY {//针对buckets vectorfor (size_type __i = 0; __i < __ht._M_buckets.size(); ++__i) {//复制vector的每一个元素(是个指针,指向节点)const _Node* __cur = __ht._M_buckets[__i];if (__cur) {_Node* __copy = _M_new_node(__cur->_M_val);_M_buckets[__i] = __copy;//针对同一个bucket list,复制每一个节点for (_Node* __next = __cur->_M_next; __next; __cur = __next, __next = __cur->_M_next) {__copy->_M_next = _M_new_node(__next->_M_val);__copy = __copy->_M_next;}}}_M_num_elements = __ht._M_num_elements; //重新记录节点个数(哈希表的大小)}__STL_UNWIND(clear());
}
template <class _Key> struct hash { };inline size_t __stl_hash_string(const char* __s)
{unsigned long __h = 0; for ( ; *__s; ++__s)__h = 5*__h + *__s;return size_t(__h);
}//以下所有的__STL_TEMPLATE_NULL在<stl_config.h>中被定义为template<>
__STL_TEMPLATE_NULL struct hash<char*>
{size_t operator()(const char* __s) const { return __stl_hash_string(__s); }
};__STL_TEMPLATE_NULL struct hash<const char*>
{size_t operator()(const char* __s) const { return __stl_hash_string(__s); }
};__STL_TEMPLATE_NULL struct hash<char> {size_t operator()(char __x) const { return __x; }
};
__STL_TEMPLATE_NULL struct hash<unsigned char> {size_t operator()(unsigned char __x) const { return __x; }
};
__STL_TEMPLATE_NULL struct hash<signed char> {size_t operator()(unsigned char __x) const { return __x; }
};
__STL_TEMPLATE_NULL struct hash<short> {size_t operator()(short __x) const { return __x; }
};
__STL_TEMPLATE_NULL struct hash<unsigned short> {size_t operator()(unsigned short __x) const { return __x; }
};
__STL_TEMPLATE_NULL struct hash<int> {size_t operator()(int __x) const { return __x; }
};
__STL_TEMPLATE_NULL struct hash<unsigned int> {size_t operator()(unsigned int __x) const { return __x; }
};
__STL_TEMPLATE_NULL struct hash<long> {size_t operator()(long __x) const { return __x; }
};
__STL_TEMPLATE_NULL struct hash<unsigned long> {size_t operator()(unsigned long __x) const { return __x; }
};
#include <hash_set> //会包含<stl_hashtable.h>
#include <iostream>
using namespace std;int main()
{hashtable<int, int, hash<int>, identity<int>, equal_to<int>, alloc>iht(50, hash<int>(), equal_to<int>());std::cout << iht.size() << std::endl; //0std::cout << iht.bucket_count()() << std::endl; //53。这是STL供应的第一个质数std::cout << iht.max_bucket_count() << std::endl; //4294967291,这是STL供应的最后一个质数iht.insert_unique(59);iht.insert_unique(63);iht.insert_unique(108);iht.insert_unique(2);iht.insert_unique(53);iht.insert_unique(55);std::cout << iht.size() << std::endl; //6。这个就是hashtable<T>::num_element//下面声明一个hashtable迭代器hashtable<int, int, hash<int>, identity<int>, equal_to<int>, alloc>::iteratorite = iht.begin();//遍历hashtablefor (int i = 0; i < iht.size(); ++i, ++ite)std::cout << *ite << std::endl; //53 55 2 108 59 53std::cout << std::endl;//遍历所有buckets。如果其节点个数不为0,就打印节点个数for (int i = 0; i < iht.bucket_count(); ++i) {int n = iht.elems_in_bucket(i);if (n != 0)std::cout << "bucket[" << i << "]has"<<n<<"elems." << std::endl;}//会打印如下内容//bucket[0] has 1 elems//bucket[2] has 3 elems//bucket[6] has 1 elems//bucket[10] has 1 elems/*为了验证bucket(list)的容量就是buckets vector的大小,这里从hastable<T>::Resize()得到结果。此处刻意将元素加到54个,看看是否发生”表格重建“*/for (int i = 0; i <= 47; ++i)iht.insert_equal(i);std::cout << iht.size() << std::endl; //54。元素(节点)个数std::cout << iht.bucket_count() << std::endl; //97,buckets个数//遍历所有buckets,如果其节点个数不为0,就打印节点个数for (int i = 0; i < iht.bucket_count(); ++i) {int n = iht.elems_in_bucket(i);if (n != 0)std::cout << "bucket[" << i << "]has" << n << "elems." << std::endl;}//打印的结果为:bucket[2]和bucket[11]的节点个数为2//其余的bucket[0]~bucket[47]的节点个数为1//此外,bucket[53],[55],[59],[63]的节点个数均为1//以迭代器遍历hashtable,将所有节点的值打印出来ite = iht.begin();for (int i = 0; i < iht.size(); ++i, ++ite)std::cout << *ite << " ";std::cout << std::endl;//0 1 2 2 3 4 5 6 7 8 9 10 11 108 12 13 14 15 16 17 18 19 20 21//22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42//43 44 45 46 47 53 55 59 63std::cout << *(iht.find(2)) << std::endl; //2std::cout << *(unt(2)) << std::endl; //2return 0;
}
iterator find(const key_type& __key)
{size_type __n = _M_bkt_num_key(__key); //查看在哪一个bucket内_Node* __first;//下面,从bucket list的头开始,一一对比每个元素的键值,对比成功就退出for ( __first = _M_buckets[__n];__first && !_M_equals(_M_get_key(__first->_M_val), __key);__first = __first->_M_next){}return iterator(__first, this);
}
size_type count(const key_type& __key) const
{const size_type __n = _M_bkt_num_key(__key); //查看在哪一个bucket内size_type __result = 0;//下面,从bucket list的头开始,一一对比每个元素的键值,对比成功就累加1for (const _Node* __cur = _M_buckets[__n]; __cur; __cur = __cur->_M_next)if (_M_equals(_M_get_key(__cur->_M_val), __key))++__result;return __result;
}
//以下代码摘录于stl_hash_set.h
template <class _Value, class _HashFcn, class _EqualKey, class _Alloc>
class hash_set
{// requirements:__STL_CLASS_REQUIRES(_Value, _Assignable);__STL_CLASS_UNARY_FUNCTION_CHECK(_HashFcn, size_t, _Value);__STL_CLASS_BINARY_FUNCTION_CHECK(_EqualKey, bool, _Value, _Value);private://indentity<>定义于<stl_function.h>中typedef hashtable<_Value, _Value, _HashFcn, _Identity<_Value>, _EqualKey, _Alloc> _Ht;_Ht _M_ht; //底层以hash table实现public:typedef typename _Ht::key_type key_type;typedef typename _Ht::value_type value_type;typedef typename _Ht::hasher hasher;typedef typename _Ht::key_equal key_equal;typedef typename _Ht::size_type size_type;typedef typename _Ht::difference_type difference_type;typedef typename _Ht::const_pointer pointer;typedef typename _Ht::const_pointer const_pointer;typedef typename _Ht::const_reference reference;typedef typename _Ht::const_reference const_reference;typedef typename _Ht::const_iterator iterator;typedef typename _Ht::const_iterator const_iterator;typedef typename _Ht::allocator_type allocator_type;hasher hash_funct() const { return _M_ht.hash_funct(); }key_equal key_eq() const { return _M_ht.key_eq(); }allocator_type get_allocator() const { return __allocator(); }public://缺省使用大小为100的表格,将被hash table调整为最接近且较大的质数hash_set(): _M_ht(100, hasher(), key_equal(), allocator_type()) {}explicit hash_set(size_type __n): _M_ht(__n, hasher(), key_equal(), allocator_type()) {}hash_set(size_type __n, const hasher& __hf): _M_ht(__n, __hf, key_equal(), allocator_type()) {}hash_set(size_type __n, const hasher& __hf, const key_equal& __eql,const allocator_type& __a = allocator_type()): _M_ht(__n, __hf, __eql, __a) {}#ifdef __STL_MEMBER_TEMPLATEStemplate <class _InputIterator>hash_set(_InputIterator __f, _InputIterator __l): _M_ht(100, hasher(), key_equal(), allocator_type()){ _M_ht.insert_unique(__f, __l); }template <class _InputIterator>hash_set(_InputIterator __f, _InputIterator __l, size_type __n): _M_ht(__n, hasher(), key_equal(), allocator_type()){ _M_ht.insert_unique(__f, __l); }template <class _InputIterator>hash_set(_InputIterator __f, _InputIterator __l, size_type __n,const hasher& __hf): _M_ht(__n, __hf, key_equal(), allocator_type()){ _M_ht.insert_unique(__f, __l); }template <class _InputIterator>hash_set(_InputIterator __f, _InputIterator __l, size_type __n,const hasher& __hf, const key_equal& __eql,const allocator_type& __a = allocator_type()): _M_ht(__n, __hf, __eql, __a){ _M_ht.insert_unique(__f, __l); }
#elsehash_set(const value_type* __f, const value_type* __l): _M_ht(100, hasher(), key_equal(), allocator_type()){ _M_ht.insert_unique(__f, __l); }hash_set(const value_type* __f, const value_type* __l, size_type __n): _M_ht(__n, hasher(), key_equal(), allocator_type()){ _M_ht.insert_unique(__f, __l); }hash_set(const value_type* __f, const value_type* __l, size_type __n,const hasher& __hf): _M_ht(__n, __hf, key_equal(), allocator_type()){ _M_ht.insert_unique(__f, __l); }hash_set(const value_type* __f, const value_type* __l, size_type __n,const hasher& __hf, const key_equal& __eql,const allocator_type& __a = allocator_type()): _M_ht(__n, __hf, __eql, __a){ _M_ht.insert_unique(__f, __l); }hash_set(const_iterator __f, const_iterator __l): _M_ht(100, hasher(), key_equal(), allocator_type()){ _M_ht.insert_unique(__f, __l); }hash_set(const_iterator __f, const_iterator __l, size_type __n): _M_ht(__n, hasher(), key_equal(), allocator_type()){ _M_ht.insert_unique(__f, __l); }hash_set(const_iterator __f, const_iterator __l, size_type __n,const hasher& __hf): _M_ht(__n, __hf, key_equal(), allocator_type()){ _M_ht.insert_unique(__f, __l); }hash_set(const_iterator __f, const_iterator __l, size_type __n,const hasher& __hf, const key_equal& __eql,const allocator_type& __a = allocator_type()): _M_ht(__n, __hf, __eql, __a){ _M_ht.insert_unique(__f, __l); }
#endif /*__STL_MEMBER_TEMPLATES */public://所有操作几乎都有hash table的对应版本。传递调用即可size_type size() const { return _M_ht.size(); }size_type max_size() const { return _M_ht.max_size(); }bool empty() const { return _pty(); }void swap(hash_set& __hs) { _M_ht.swap(__hs._M_ht); }#ifdef __STL_MEMBER_TEMPLATEStemplate <class _Val, class _HF, class _EqK, class _Al> friend bool operator== (const hash_set<_Val, _HF, _EqK, _Al>&,const hash_set<_Val, _HF, _EqK, _Al>&);
#else /* __STL_MEMBER_TEMPLATES */friend bool __STD_QUALIFIERoperator== __STL_NULL_TMPL_ARGS (const hash_set&, const hash_set&);
#endif /* __STL_MEMBER_TEMPLATES */iterator begin() const { return _M_ht.begin(); }iterator end() const { return _d(); }public:pair<iterator, bool> insert(const value_type& __obj){pair<typename _Ht::iterator, bool> __p = _M_ht.insert_unique(__obj);return pair<iterator,bool>(__p.first, __p.second);}
#ifdef __STL_MEMBER_TEMPLATEStemplate <class _InputIterator>void insert(_InputIterator __f, _InputIterator __l) { _M_ht.insert_unique(__f,__l); }
#elsevoid insert(const value_type* __f, const value_type* __l) {_M_ht.insert_unique(__f,__l);}void insert(const_iterator __f, const_iterator __l) {_M_ht.insert_unique(__f, __l); }
#endif /*__STL_MEMBER_TEMPLATES */pair<iterator, bool> insert_noresize(const value_type& __obj){pair<typename _Ht::iterator, bool> __p = _M_ht.insert_unique_noresize(__obj);return pair<iterator, bool>(__p.first, __p.second);}iterator find(const key_type& __key) const { return _M_ht.find(__key); }size_type count(const key_type& __key) const { return _unt(__key); }pair<iterator, iterator> equal_range(const key_type& __key) const{ return _M_ht.equal_range(__key); }size_type erase(const key_type& __key) {return _ase(__key); }void erase(iterator __it) { _ase(__it); }void erase(iterator __f, iterator __l) { _ase(__f, __l); }void clear() { _M_ht.clear(); }public:void resize(size_type __hint) { _size(__hint); }size_type bucket_count() const { return _M_ht.bucket_count(); }size_type max_bucket_count() const { return _M_ht.max_bucket_count(); }size_type elems_in_bucket(size_type __n) const{ return _M_ht.elems_in_bucket(__n); }
};template <class _Value, class _HashFcn, class _EqualKey, class _Alloc>
inline bool
operator==(const hash_set<_Value,_HashFcn,_EqualKey,_Alloc>& __hs1,const hash_set<_Value,_HashFcn,_EqualKey,_Alloc>& __hs2)
{return __hs1._M_ht == __hs2._M_ht;
}
#include <iostream>
#include <hash_set>
#include <string.h>
using namespace std;struct eqstr
{bool operator()(const char* s1, const char* s2){return strcmp(s1, s2) == 0;}
};void loopup(const hash_set<const char*, hash<const char*>, eqstr>& Set,const char* word)
{hash_set<const char*, hash<const char*>, eqstr>::const_iterator it = Set.find(word);std::cout << " " << word << ": " << (it != d() ? "present" : "not present") << std::endl;
}int main()
{hash_set<const char*, hash<const char*>, eqstr> Set;Set.insert("kiwi");Set.insert("plum");Set.insert("apple");Set.insert("mango");Set.insert("apricot");Set.insert("banana");loopup(Set, "mango"); //mango: presentloopup(Set, "apple"); //apple: presentloopup(Set, "durian"); //durian: not present//ite1类型为hash_set<const char*, hash<const char*>, eqstr>::iteratorauto iter = Set.begin();for (; iter != d(); ++iter)std::cout << *iter << ""; //banana plum mango apple kiwi apricotstd::cout << std::endl;return 0;
}
int main()
{hash_set<int> Set; //hash_set默认缺省为100。SGI内部采用质数193Set.insert(3); //实际大小为193Set.insert(196);Set.insert(1);Set.insert(389);Set.insert(194);Set.insert(387);//ite1类型为hash_set<const char*, hash<const char*>, eqstr>::iteratorauto iter = Set.begin();for (; iter != d(); ++iter)std::cout << *iter << ""; //387 194 1 389 196 3std::cout << std::endl;return 0;
}
//以下代码摘录于stl_hash_map.h
//以下的hash<>是个function object,定义于<stl_hash_fun.h>中
//例如:hash<int>::operator()(int x)const{return x;}
template <class _Key, class _Tp, class _HashFcn, class _EqualKey,class _Alloc>
class hash_map
{// requirements:__STL_CLASS_REQUIRES(_Key, _Assignable);__STL_CLASS_REQUIRES(_Tp, _Assignable);__STL_CLASS_UNARY_FUNCTION_CHECK(_HashFcn, size_t, _Key);__STL_CLASS_BINARY_FUNCTION_CHECK(_EqualKey, bool, _Key, _Key);private://以下使用的select1st<>定义在<stl_function.h>中typedef hashtable<pair<const _Key,_Tp>,_Key,_HashFcn,_Select1st<pair<const _Key,_Tp> >,_EqualKey,_Alloc> _Ht;_Ht _M_ht;public:typedef typename _Ht::key_type key_type;typedef _Tp data_type;typedef _Tp mapped_type;typedef typename _Ht::value_type value_type;typedef typename _Ht::hasher hasher;typedef typename _Ht::key_equal key_equal;typedef typename _Ht::size_type size_type;typedef typename _Ht::difference_type difference_type;typedef typename _Ht::pointer pointer;typedef typename _Ht::const_pointer const_pointer;typedef typename _Ht::reference reference;typedef typename _Ht::const_reference const_reference;typedef typename _Ht::iterator iterator;typedef typename _Ht::const_iterator const_iterator;typedef typename _Ht::allocator_type allocator_type;hasher hash_funct() const { return _M_ht.hash_funct(); }key_equal key_eq() const { return _M_ht.key_eq(); }allocator_type get_allocator() const { return __allocator(); }public://缺省使用大小为100的表格,将被hash table调整为最接近且较大的质数hash_map() : _M_ht(100, hasher(), key_equal(), allocator_type()) {}explicit hash_map(size_type __n): _M_ht(__n, hasher(), key_equal(), allocator_type()) {}hash_map(size_type __n, const hasher& __hf): _M_ht(__n, __hf, key_equal(), allocator_type()) {}hash_map(size_type __n, const hasher& __hf, const key_equal& __eql,const allocator_type& __a = allocator_type()): _M_ht(__n, __hf, __eql, __a) {}#ifdef __STL_MEMBER_TEMPLATEStemplate <class _InputIterator>hash_map(_InputIterator __f, _InputIterator __l): _M_ht(100, hasher(), key_equal(), allocator_type()){ _M_ht.insert_unique(__f, __l); }template <class _InputIterator>hash_map(_InputIterator __f, _InputIterator __l, size_type __n): _M_ht(__n, hasher(), key_equal(), allocator_type()){ _M_ht.insert_unique(__f, __l); }template <class _InputIterator>hash_map(_InputIterator __f, _InputIterator __l, size_type __n,const hasher& __hf): _M_ht(__n, __hf, key_equal(), allocator_type()){ _M_ht.insert_unique(__f, __l); }template <class _InputIterator>hash_map(_InputIterator __f, _InputIterator __l, size_type __n,const hasher& __hf, const key_equal& __eql,const allocator_type& __a = allocator_type()): _M_ht(__n, __hf, __eql, __a){ _M_ht.insert_unique(__f, __l); }#elsehash_map(const value_type* __f, const value_type* __l): _M_ht(100, hasher(), key_equal(), allocator_type()){ _M_ht.insert_unique(__f, __l); }hash_map(const value_type* __f, const value_type* __l, size_type __n): _M_ht(__n, hasher(), key_equal(), allocator_type()){ _M_ht.insert_unique(__f, __l); }hash_map(const value_type* __f, const value_type* __l, size_type __n,const hasher& __hf): _M_ht(__n, __hf, key_equal(), allocator_type()){ _M_ht.insert_unique(__f, __l); }hash_map(const value_type* __f, const value_type* __l, size_type __n,const hasher& __hf, const key_equal& __eql,const allocator_type& __a = allocator_type()): _M_ht(__n, __hf, __eql, __a){ _M_ht.insert_unique(__f, __l); }hash_map(const_iterator __f, const_iterator __l): _M_ht(100, hasher(), key_equal(), allocator_type()){ _M_ht.insert_unique(__f, __l); }hash_map(const_iterator __f, const_iterator __l, size_type __n): _M_ht(__n, hasher(), key_equal(), allocator_type()){ _M_ht.insert_unique(__f, __l); }hash_map(const_iterator __f, const_iterator __l, size_type __n,const hasher& __hf): _M_ht(__n, __hf, key_equal(), allocator_type()){ _M_ht.insert_unique(__f, __l); }hash_map(const_iterator __f, const_iterator __l, size_type __n,const hasher& __hf, const key_equal& __eql,const allocator_type& __a = allocator_type()): _M_ht(__n, __hf, __eql, __a){ _M_ht.insert_unique(__f, __l); }
#endif /*__STL_MEMBER_TEMPLATES */public://所有操作几乎都有hash table的对应版本。传递调用即可size_type size() const { return _M_ht.size(); }size_type max_size() const { return _M_ht.max_size(); }bool empty() const { return _pty(); }void swap(hash_map& __hs) { _M_ht.swap(__hs._M_ht); }#ifdef __STL_MEMBER_TEMPLATEStemplate <class _K1, class _T1, class _HF, class _EqK, class _Al>friend bool operator== (const hash_map<_K1, _T1, _HF, _EqK, _Al>&,const hash_map<_K1, _T1, _HF, _EqK, _Al>&);
#else /* __STL_MEMBER_TEMPLATES */friend bool __STD_QUALIFIERoperator== __STL_NULL_TMPL_ARGS (const hash_map&, const hash_map&);
#endif /* __STL_MEMBER_TEMPLATES */iterator begin() { return _M_ht.begin(); }iterator end() { return _d(); }const_iterator begin() const { return _M_ht.begin(); }const_iterator end() const { return _d(); }public:pair<iterator,bool> insert(const value_type& __obj){ return _M_ht.insert_unique(__obj); }
#ifdef __STL_MEMBER_TEMPLATEStemplate <class _InputIterator>void insert(_InputIterator __f, _InputIterator __l){ _M_ht.insert_unique(__f,__l); }
#elsevoid insert(const value_type* __f, const value_type* __l) {_M_ht.insert_unique(__f,__l);}void insert(const_iterator __f, const_iterator __l){ _M_ht.insert_unique(__f, __l); }
#endif /*__STL_MEMBER_TEMPLATES */pair<iterator,bool> insert_noresize(const value_type& __obj){ return _M_ht.insert_unique_noresize(__obj); } iterator find(const key_type& __key) { return _M_ht.find(__key); }const_iterator find(const key_type& __key) const { return _M_ht.find(__key); }_Tp& operator[](const key_type& __key) {return _M_ht.find_or_insert(value_type(__key, _Tp())).second;}size_type count(const key_type& __key) const { return _unt(__key); }pair<iterator, iterator> equal_range(const key_type& __key){ return _M_ht.equal_range(__key); }pair<const_iterator, const_iterator>equal_range(const key_type& __key) const{ return _M_ht.equal_range(__key); }size_type erase(const key_type& __key) {return _ase(__key); }void erase(iterator __it) { _ase(__it); }void erase(iterator __f, iterator __l) { _ase(__f, __l); }void clear() { _M_ht.clear(); }void resize(size_type __hint) { _size(__hint); }size_type bucket_count() const { return _M_ht.bucket_count(); }size_type max_bucket_count() const { return _M_ht.max_bucket_count(); }size_type elems_in_bucket(size_type __n) const{ return _M_ht.elems_in_bucket(__n); }
};template <class _Key, class _Tp, class _HashFcn, class _EqlKey, class _Alloc>
inline bool
operator==(const hash_map<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm1,const hash_map<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm2)
{return __hm1._M_ht == __hm2._M_ht;
}
#include <iostream>
#include <hash_map>
#include <string.h>
using namespace std;struct eqstr
{bool operator()(const char* s1, const char* s2){return strcmp(s1, s2) == 0;}
};int main()
{hash_map<const char*, int,hash<const char*>, eqstr> days;days["january"] = 31;days["february"] = 28;days["march"] = 31;days["april"] = 30;days["may"] = 31;days["june"] = 30;days["july"] = 31;days["august"] = 31;days["september"] = 30;days["october"] = 31;days["november"] = 30;days["december"] = 31;std::cout << "september ->" << days["september"] << std::endl;//30std::cout << "june ->" << days["june"] << std::endl; //30std::cout << "february ->" << days["february"] << std::endl; //28std::cout << "december ->" << days["december"] << std::endl; //31//ite1类型为hash_map<const char*, int,hash<const char*>, eqstr>::iteratorauto iter = days.begin();for (; iter != d(); ++iter)std::cout << iter->first << "";//september june july may january february december //march april november october auguststd::cout << std::endl;return 0;
}
本文发布于:2024-01-31 12:23:39,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170667502028491.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |