stl_hashtable.h
// Filename: stl_hashtable.h // Comment By: 凝霜
// E-mail: mdl2009@vip.qq.com
// Blog: http://blog.csdn.net/mdl13412 ////////////////////////////////////////////////////////////////////////////////
// 本实作的hashtable采用的是开链法, 其内存布局如下
////////////////////////////////////////////////////////////////////////////////
// 对于产生哈希冲突的结点, 我们采取在其位置维护一个链表才处理之
//
// ------------------------------------------------------------------------
// | | | | | | ..... | | | | |
// ------------------------------------------------------------------------
// | | |
// ↓ ↓ ↓
// -------- -------- -------- -------- --------
// | next |->0 | next |->| next |->| next |->0 | next |->0
// -------- -------- -------- -------- --------
// | data | | data | | data | | data | | data |
// -------- -------- -------- -------- --------
//////////////////////////////////////////////////////////////////////////////// /*
* Copyright (c) 1996,1997
* Silicon Graphics Computer Systems, Inc.
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Silicon Graphics makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
*
* Copyright (c) 1994
* Hewlett-Packard Company
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Hewlett-Packard Company makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
*/ /* NOTE: This is an internal header file, included by other STL headers.
* You should not attempt to use it directly.
*/ #ifndef __SGI_STL_INTERNAL_HASHTABLE_H
#define __SGI_STL_INTERNAL_HASHTABLE_H // hashtable类用于实现哈希关联容器hash_st, hash_map, hash_multiset和hash_multimap #include <stl_algobase.h>
#include <stl_alloc.h>
#include <stl_construct.h>
#include <stl_tempbuf.h>
#include <stl_algo.h>
#include <stl_uninitialized.h>
#include <stl_function.h>
#include <stl_vector.h>
#include <stl_hash_fun.h> __STL_BEGIN_NAMESPACE // 这个是哈希表中维护的链表结点
template <class Value>
struct __hashtable_node
{
__hashtable_node* next;
Value val;
}; // 这里使用前置声明, 否则后面的交叉引用会导致编译错误
template <class Value, class Key, class HashFcn,
class ExtractKey, class EqualKey, class Alloc = alloc>
class hashtable; template <class Value, class Key, class HashFcn,
class ExtractKey, class EqualKey, class Alloc>
struct __hashtable_iterator; template <class Value, class Key, class HashFcn,
class ExtractKey, class EqualKey, class Alloc>
struct __hashtable_const_iterator; template <class Value, class Key, class HashFcn,
class ExtractKey, class EqualKey, class Alloc>
struct __hashtable_iterator
{
// 注意: hashtable不提供reverse iterator, 也不提供operator --
typedef hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>
hashtable;
typedef __hashtable_iterator<Value, Key, HashFcn,
ExtractKey, EqualKey, Alloc>
iterator;
typedef __hashtable_const_iterator<Value, Key, HashFcn,
ExtractKey, EqualKey, Alloc>
const_iterator;
typedef __hashtable_node<Value> node; typedef forward_iterator_tag iterator_category;
typedef Value value_type;
typedef ptrdiff_t difference_type;
typedef size_t size_type;
typedef Value& reference;
typedef Value* pointer; // 本实作中hasntable是由一个线性表作为hash表, 而表内的每一个被映射的
// 哈希结点内部维护这一个链表, 用于处理哈希冲突, 此即开链法
node* cur; // 当前的位置, 是线性表中的链表结点
hashtable* ht; // 线性表中的位置 __hashtable_iterator(node* n, hashtable* tab) : cur(n), ht(tab) {}
__hashtable_iterator() {} reference operator*() const { return cur->val; } #ifndef __SGI_STL_NO_ARROW_OPERATOR
// 如果编译器支持'->'则重载, 详细见我在<stl_list.h>中的剖析
pointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */ // 详细解析见实现部分
iterator& operator++();
iterator operator++(int); bool operator==(const iterator& it) const { return cur == it.cur; }
bool operator!=(const iterator& it) const { return cur != it.cur; }
}; // const情况基本和上面一致
template <class Value, class Key, class HashFcn,
class ExtractKey, class EqualKey, class Alloc>
struct __hashtable_const_iterator
{
typedef hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>
hashtable;
typedef __hashtable_iterator<Value, Key, HashFcn,
ExtractKey, EqualKey, Alloc>
iterator;
typedef __hashtable_const_iterator<Value, Key, HashFcn,
ExtractKey, EqualKey, Alloc>
const_iterator;
typedef __hashtable_node<Value> node; typedef forward_iterator_tag iterator_category;
typedef Value value_type;
typedef ptrdiff_t difference_type;
typedef size_t size_type;
typedef const Value& reference;
typedef const Value* pointer; const node* cur;
const hashtable* ht; __hashtable_const_iterator(const node* n, const hashtable* tab)
: cur(n), ht(tab) {}
__hashtable_const_iterator() {}
__hashtable_const_iterator(const iterator& it) : cur(it.cur), ht(it.ht) {}
reference operator*() const { return cur->val; }
#ifndef __SGI_STL_NO_ARROW_OPERATOR
pointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */
const_iterator& operator++();
const_iterator operator++(int);
bool operator==(const const_iterator& it) const { return cur == it.cur; }
bool operator!=(const const_iterator& it) const { return cur != it.cur; }
}; // 假设long至少为32-bits, 否则根据情况自己修改
static const int __stl_num_primes = ;
static const unsigned long __stl_prime_list[__stl_num_primes] =
{
, , , , ,
, , , , ,
, , , , ,
, , , , ,
, , , , ,
, 3221225473ul, 4294967291ul
}; // 返回大于n的最小素数
inline unsigned long __stl_next_prime(unsigned long n)
{
const unsigned long* first = __stl_prime_list;
const unsigned long* last = __stl_prime_list + __stl_num_primes;
const unsigned long* pos = lower_bound(first, last, n);
return pos == last ? *(last - ) : *pos;
} // Value: 结点的valule类型
// Key: 结点的key类型
// HashFcn: hash function
// ExtractKey: 从结点中取出键值的方法
// EqualKey: 判断键值是否相同的方法
// Alloc: allocator, 默认alloc
template <class Value, class Key, class HashFcn,
class ExtractKey, class EqualKey,
class Alloc>
class hashtable
{
public:
typedef Key key_type;
typedef Value value_type;
typedef HashFcn hasher;
typedef EqualKey key_equal; 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; // 获取hash相关的函数
hasher hash_funct() const { return hash; }
key_equal key_eq() const { return equals; } private:
// 详细剖析参考<stl_fun_fun.h>
hasher hash;
key_equal equals;
ExtractKey get_key; typedef __hashtable_node<Value> node;
typedef simple_alloc<node, Alloc> node_allocator; vector<node*,Alloc> buckets; // 线性表以vector实作
size_type num_elements; public:
typedef __hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey,
Alloc>
iterator; typedef __hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey,
Alloc>
const_iterator; friend struct
__hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>;
friend struct
__hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>; public:
// 下面这些函数STL容器的表现基本一致,
// 不做说明, 可以参看<stl_vector.h>, <stl_list.h>中的解析
hashtable(size_type n,
const HashFcn& hf,
const EqualKey& eql,
const ExtractKey& ext)
: hash(hf), equals(eql), get_key(ext), num_elements()
{
initialize_buckets(n);
} hashtable(size_type n,
const HashFcn& hf,
const EqualKey& eql)
: hash(hf), equals(eql), get_key(ExtractKey()), num_elements()
{
initialize_buckets(n);
} hashtable(const hashtable& ht)
: hash(ht.hash), equals(ht.equals), get_key(ht.get_key), num_elements()
{
copy_from(ht);
} hashtable& operator= (const hashtable& ht)
{
if (&ht != this) {
clear();
hash = ht.hash;
equals = ht.equals;
get_key = ht.get_key;
copy_from(ht);
}
return *this;
} ~hashtable() { clear(); } size_type size() const { return num_elements; }
size_type max_size() const { return size_type(-); }
bool empty() const { return size() == ; } void swap(hashtable& ht)
{
__STD::swap(hash, ht.hash);
__STD::swap(equals, ht.equals);
__STD::swap(get_key, ht.get_key);
buckets.swap(ht.buckets);
__STD::swap(num_elements, ht.num_elements);
} iterator begin()
{
for (size_type n = ; n < buckets.size(); ++n)
if (buckets[n])
return iterator(buckets[n], this);
return end();
} iterator end() { return iterator(, this); } const_iterator begin() const
{
for (size_type n = ; n < buckets.size(); ++n)
if (buckets[n])
return const_iterator(buckets[n], this);
return end();
} const_iterator end() const { return const_iterator(, this); } friend bool
operator== __STL_NULL_TMPL_ARGS (const hashtable&, const hashtable&); public:
// 线性表中的结点数
size_type bucket_count() const { return buckets.size(); } // 线性表最多能分配的结点数
size_type max_bucket_count() const
{ return __stl_prime_list[__stl_num_primes - ]; } // 返回指定key映射了多少value
size_type elems_in_bucket(size_type bucket) const
{
size_type result = ;
for (node* cur = buckets[bucket]; cur; cur = cur->next)
result += ;
return result;
} // 插入操作, 不允许重复
pair<iterator, bool> insert_unique(const value_type& obj)
{
// 首先判断容量是否够用, 否则就重新配置
resize(num_elements + );
return insert_unique_noresize(obj);
} // 插入操作, 允许重复
iterator insert_equal(const value_type& obj)
{
resize(num_elements + );
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_TEMPLATES
template <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 = ;
distance(f, l, n);
resize(num_elements + n);
for ( ; n > ; --n, ++f)
insert_unique_noresize(*f);
} template <class ForwardIterator>
void insert_equal(ForwardIterator f, ForwardIterator l,
forward_iterator_tag)
{
size_type n = ;
distance(f, l, n);
resize(num_elements + n);
for ( ; n > ; --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(num_elements + n);
for ( ; n > ; --n, ++f)
insert_unique_noresize(*f);
} void insert_equal(const value_type* f, const value_type* l)
{
size_type n = l - f;
resize(num_elements + n);
for ( ; n > ; --n, ++f)
insert_equal_noresize(*f);
} void insert_unique(const_iterator f, const_iterator l)
{
size_type n = ;
distance(f, l, n);
resize(num_elements + n);
for ( ; n > ; --n, ++f)
insert_unique_noresize(*f);
} void insert_equal(const_iterator f, const_iterator l)
{
size_type n = ;
distance(f, l, n);
resize(num_elements + n);
for ( ; n > ; --n, ++f)
insert_equal_noresize(*f);
}
#endif /*__STL_MEMBER_TEMPLATES */ reference find_or_insert(const value_type& obj); // 查找指定key
iterator find(const key_type& key)
{
size_type n = bkt_num_key(key);
node* first;
for ( first = buckets[n];
first && !equals(get_key(first->val), key);
first = first->next)
{}
return iterator(first, this);
} const_iterator find(const key_type& key) const
{
size_type n = bkt_num_key(key);
const node* first;
for ( first = buckets[n];
first && !equals(get_key(first->val), key);
first = first->next)
{}
return const_iterator(first, this);
} // 返回key元素的个数
size_type count(const key_type& key) const
{
const size_type n = bkt_num_key(key);
size_type result = ; for (const node* cur = buckets[n]; cur; cur = cur->next)
if (equals(get_key(cur->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 next_size(size_type n) const { return __stl_next_prime(n); } // 预留空间, 并进行初始化
void initialize_buckets(size_type n)
{
const size_type n_buckets = next_size(n);
buckets.reserve(n_buckets);
buckets.insert(buckets.end(), n_buckets, (node*) );
num_elements = ;
} size_type bkt_num_key(const key_type& key) const
{
return bkt_num_key(key, buckets.size());
} // 获取obj映射位置, 要经过一个mod过程
size_type bkt_num(const value_type& obj) const
{
return bkt_num_key(get_key(obj));
} size_type bkt_num_key(const key_type& key, size_t n) const
{
return hash(key) % n;
} size_type bkt_num(const value_type& obj, size_t n) const
{
return bkt_num_key(get_key(obj), n);
} // 分配空间并进行构造
node* new_node(const value_type& obj)
{
node* n = node_allocator::allocate();
n->next = ;
__STL_TRY {
construct(&n->val, obj);
return n;
}
__STL_UNWIND(node_allocator::deallocate(n));
} // 析构并释放空间
void delete_node(node* n)
{
destroy(&n->val);
node_allocator::deallocate(n);
} // 解析见实现部分
void erase_bucket(const size_type n, node* first, node* last);
void erase_bucket(const size_type n, node* last); void copy_from(const hashtable& ht);
}; template <class V, class K, class HF, class ExK, class EqK, class A>
__hashtable_iterator<V, K, HF, ExK, EqK, A>&
__hashtable_iterator<V, K, HF, ExK, EqK, A>::operator++()
{
const node* old = cur;
cur = cur->next; // 当前链表结点的下一个结点, 如果不为0
// 那么它就是我们要的 // 链表结点恰好是最后一个结点, 我们要在线性表的下一个表格的链表中查找
if (!cur)
{
size_type bucket = ht->bkt_num(old->val);
while (!cur && ++bucket < ht->buckets.size())
cur = ht->buckets[bucket];
} return *this;
} template <class V, class K, class HF, class ExK, class EqK, class A>
inline __hashtable_iterator<V, K, HF, ExK, EqK, A>
__hashtable_iterator<V, K, HF, ExK, EqK, A>::operator++(int)
{
iterator tmp = *this;
++*this; // 触发operator ++()
return tmp;
} // const情况同上
template <class V, class K, class HF, class ExK, class EqK, class A>
__hashtable_const_iterator<V, K, HF, ExK, EqK, A>&
__hashtable_const_iterator<V, K, HF, ExK, EqK, A>::operator++()
{
const node* old = cur;
cur = cur->next;
if (!cur) {
size_type bucket = ht->bkt_num(old->val);
while (!cur && ++bucket < ht->buckets.size())
cur = ht->buckets[bucket];
}
return *this;
} template <class V, class K, class HF, class ExK, class EqK, class A>
inline __hashtable_const_iterator<V, K, HF, ExK, EqK, A>
__hashtable_const_iterator<V, K, HF, ExK, EqK, A>::operator++(int)
{
const_iterator tmp = *this;
++*this;
return tmp;
} // 对于不支持偏特化的编译器提供traits支持
#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION template <class V, class K, class HF, class ExK, class EqK, class All>
inline forward_iterator_tag
iterator_category(const __hashtable_iterator<V, K, HF, ExK, EqK, All>&)
{
return forward_iterator_tag();
} template <class V, class K, class HF, class ExK, class EqK, class All>
inline V* value_type(const __hashtable_iterator<V, K, HF, ExK, EqK, All>&)
{
return (V*) ;
} template <class V, class K, class HF, class ExK, class EqK, class All>
inline hashtable<V, K, HF, ExK, EqK, All>::difference_type*
distance_type(const __hashtable_iterator<V, K, HF, ExK, EqK, All>&)
{
return (hashtable<V, K, HF, ExK, EqK, All>::difference_type*) ;
} template <class V, class K, class HF, class ExK, class EqK, class All>
inline forward_iterator_tag
iterator_category(const __hashtable_const_iterator<V, K, HF, ExK, EqK, All>&)
{
return forward_iterator_tag();
} template <class V, class K, class HF, class ExK, class EqK, class All>
inline V*
value_type(const __hashtable_const_iterator<V, K, HF, ExK, EqK, All>&)
{
return (V*) ;
} template <class V, class K, class HF, class ExK, class EqK, class All>
inline hashtable<V, K, HF, ExK, EqK, All>::difference_type*
distance_type(const __hashtable_const_iterator<V, K, HF, ExK, EqK, All>&)
{
return (hashtable<V, K, HF, ExK, EqK, All>::difference_type*) ;
} #endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */ template <class V, class K, class HF, class Ex, class Eq, class A>
bool operator==(const hashtable<V, K, HF, Ex, Eq, A>& ht1,
const hashtable<V, K, HF, Ex, Eq, A>& ht2)
{
typedef typename hashtable<V, K, HF, Ex, Eq, A>::node node;
if (ht1.buckets.size() != ht2.buckets.size())
return false;
for (int n = ; n < ht1.buckets.size(); ++n) {
node* cur1 = ht1.buckets[n];
node* cur2 = ht2.buckets[n];
for ( ; cur1 && cur2 && cur1->val == cur2->val;
cur1 = cur1->next, cur2 = cur2->next)
{}
if (cur1 || cur2)
return false;
}
return true;
} // 如果编译器支持模板函数特化优先级
// 那么将全局的swap实现为使用hashtable私有的swap以提高效率
#ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER template <class Val, class Key, class HF, class Extract, class EqKey, class A>
inline void swap(hashtable<Val, Key, HF, Extract, EqKey, A>& ht1,
hashtable<Val, Key, HF, Extract, EqKey, A>& ht2) {
ht1.swap(ht2);
} #endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */ // 在不需要重新调整容量的情况下插入元素, key不可以重复
template <class V, class K, class HF, class Ex, class Eq, class A>
pair<typename hashtable<V, K, HF, Ex, Eq, A>::iterator, bool>
hashtable<V, K, HF, Ex, Eq, A>::insert_unique_noresize(const value_type& obj)
{
// 获取待插入元素在hashtable中的索引
const size_type n = bkt_num(obj); node* first = buckets[n]; for (node* cur = first; cur; cur = cur->next)
// 如果keu重复, 在不进行插入, 并告知用户插入失败
if (equals(get_key(cur->val), get_key(obj)))
return pair<iterator, bool>(iterator(cur, this), false); // 插入结点
node* tmp = new_node(obj);
tmp->next = first;
buckets[n] = tmp;
++num_elements;
return pair<iterator, bool>(iterator(tmp, this), true);
} // 在不需要重新调整容量的情况下插入元素, key可以重复
template <class V, class K, class HF, class Ex, class Eq, class A>
typename hashtable<V, K, HF, Ex, Eq, A>::iterator
hashtable<V, K, HF, Ex, Eq, A>::insert_equal_noresize(const value_type& obj)
{
const size_type n = bkt_num(obj);
node* first = buckets[n]; for (node* cur = first; cur; cur = cur->next)
if (equals(get_key(cur->val), get_key(obj))) {
node* tmp = new_node(obj);
tmp->next = cur->next;
cur->next = tmp;
++num_elements;
return iterator(tmp, this);
} node* tmp = new_node(obj);
tmp->next = first;
buckets[n] = tmp;
++num_elements;
return iterator(tmp, this);
} // 这个用于支持hash_map操作
template <class V, class K, class HF, class Ex, class Eq, class A>
typename hashtable<V, K, HF, Ex, Eq, A>::reference
hashtable<V, K, HF, Ex, Eq, A>::find_or_insert(const value_type& obj)
{
resize(num_elements + ); size_type n = bkt_num(obj);
node* first = buckets[n]; for (node* cur = first; cur; cur = cur->next)
if (equals(get_key(cur->val), get_key(obj)))
return cur->val; node* tmp = new_node(obj);
tmp->next = first;
buckets[n] = tmp;
++num_elements;
return tmp->val;
} // 查找满足key的区间
template <class V, class K, class HF, class Ex, class Eq, class A>
pair<typename hashtable<V, K, HF, Ex, Eq, A>::iterator,
typename hashtabfind_or_insertle<V, K, HF, Ex, Eq, A>::iterator>
hashtable<V, K, HF, Ex, Eq, A>::equal_range(const key_type& key)
{
typedef pair<iterator, iterator> pii;
const size_type n = bkt_num_key(key); for (node* first = buckets[n]; first; first = first->next) {
if (equals(get_key(first->val), key)) {
for (node* cur = first->next; cur; cur = cur->next)
if (!equals(get_key(cur->val), key))
return pii(iterator(first, this), iterator(cur, this));
for (size_type m = n + ; m < buckets.size(); ++m)
if (buckets[m])
return pii(iterator(first, this),
iterator(buckets[m], this));
return pii(iterator(first, this), end());
}
}
return pii(end(), end());
} template <class V, class K, class HF, class Ex, class Eq, class A>
pair<typename hashtable<V, K, HF, Ex, Eq, A>::const_iterator,
typename hashtable<V, K, HF, Ex, Eq, A>::const_iterator>
hashtable<V, K, HF, Ex, Eq, A>::equal_range(const key_type& key) const
{
typedef pair<const_iterator, const_iterator> pii;
const size_type n = bkt_num_key(key); for (const node* first = buckets[n] ; first; first = first->next) {
if (equals(get_key(first->val), key)) {
for (const node* cur = first->next; cur; cur = cur->next)
if (!equals(get_key(cur->val), key))
return pii(const_iterator(first, this),
const_iterator(cur, this));
for (size_type m = n + ; m < buckets.size(); ++m)
if (buckets[m])
return pii(const_iterator(first, this),
const_iterator(buckets[m], this));
return pii(const_iterator(first, this), end());
}
}
return pii(end(), end());
} // 擦除指定元素
template <class V, class K, class HF, class Ex, class Eq, class A>
typename hashtable<V, K, HF, Ex, Eq, A>::size_type
hashtable<V, K, HF, Ex, Eq, A>::erase(const key_type& key)
{
// 计算映射位置
const size_type n = bkt_num_key(key);
node* first = buckets[n];
size_type erased = ; // 开始查找并删除
if (first) {
node* cur = first;
node* next = cur->next;
while (next) {
if (equals(get_key(next->val), key)) {
cur->next = next->next;
delete_node(next);
next = cur->next;
++erased;
--num_elements;
}
else {
cur = next;
next = cur->next;
}
}
if (equals(get_key(first->val), key)) {
buckets[n] = first->next;
delete_node(first);
++erased;
--num_elements;
}
}
return erased;
} template <class V, class K, class HF, class Ex, class Eq, class A>
void hashtable<V, K, HF, Ex, Eq, A>::erase(const iterator& it)
{
if (node* const p = it.cur) {
const size_type n = bkt_num(p->val);
node* cur = buckets[n]; if (cur == p) {
buckets[n] = cur->next;
delete_node(cur);
--num_elements;
}
else {
node* next = cur->next;
while (next) {
if (next == p) {
cur->next = next->next;
delete_node(next);
--num_elements;
break;
}
else {
cur = next;
next = cur->next;
}
}
}
}
} // 擦除指定区间的元素
template <class V, class K, class HF, class Ex, class Eq, class A>
void hashtable<V, K, HF, Ex, Eq, A>::erase(iterator first, iterator last)
{
size_type f_bucket = first.cur ? bkt_num(first.cur->val) : buckets.size();
size_type l_bucket = last.cur ? bkt_num(last.cur->val) : buckets.size(); if (first.cur == last.cur)
return;
else if (f_bucket == l_bucket)
erase_bucket(f_bucket, first.cur, last.cur);
else {
erase_bucket(f_bucket, first.cur, );
for (size_type n = f_bucket + ; n < l_bucket; ++n)
erase_bucket(n, );
if (l_bucket != buckets.size())
erase_bucket(l_bucket, last.cur);
}
} template <class V, class K, class HF, class Ex, class Eq, class A>
inline void
hashtable<V, K, HF, Ex, Eq, A>::erase(const_iterator first,
const_iterator last)
{
erase(iterator(const_cast<node*>(first.cur),
const_cast<hashtable*>(first.ht)),
iterator(const_cast<node*>(last.cur),
const_cast<hashtable*>(last.ht)));
} template <class V, class K, class HF, class Ex, class Eq, class A>
inline void
hashtable<V, K, HF, Ex, Eq, A>::erase(const const_iterator& it)
{
erase(iterator(const_cast<node*>(it.cur),
const_cast<hashtable*>(it.ht)));
} // 调整hashtable的容量
template <class V, class K, class HF, class Ex, class Eq, class A>
void hashtable<V, K, HF, Ex, Eq, A>::resize(size_type num_elements_hint)
{
const size_type old_n = buckets.size(); // 如果新调整的大小小于当前大小, 不进行更改
if (num_elements_hint > old_n) {
const size_type n = next_size(num_elements_hint); // 如果已经到达hashtable的容量的极限, 那么也不进行更改
if (n > old_n) {
// 建立新的线性表来扩充容量
vector<node*, A> tmp(n, (node*) );
__STL_TRY {
// 先面开始copy
for (size_type bucket = ; bucket < old_n; ++bucket) {
node* first = buckets[bucket];
while (first) {
size_type new_bucket = bkt_num(first->val, n);
buckets[bucket] = first->next;
first->next = tmp[new_bucket];
tmp[new_bucket] = first;
first = buckets[bucket];
}
}
buckets.swap(tmp);
}
# ifdef __STL_USE_EXCEPTIONS
catch(...) {
for (size_type bucket = ; bucket < tmp.size(); ++bucket) {
while (tmp[bucket]) {
node* next = tmp[bucket]->next;
delete_node(tmp[bucket]);
tmp[bucket] = next;
}
}
throw;
}
# endif /* __STL_USE_EXCEPTIONS */
}
}
} // 擦除指定映射位置的所有元素
template <class V, class K, class HF, class Ex, class Eq, class A>
void hashtable<V, K, HF, Ex, Eq, A>::erase_bucket(const size_type n,
node* first, node* last)
{
node* cur = buckets[n];
if (cur == first)
erase_bucket(n, last);
else {
node* next;
for (next = cur->next; next != first; cur = next, next = cur->next)
;
while (next) {
cur->next = next->next;
delete_node(next);
next = cur->next;
--num_elements;
}
}
} template <class V, class K, class HF, class Ex, class Eq, class A>
void
hashtable<V, K, HF, Ex, Eq, A>::erase_bucket(const size_type n, node* last)
{
node* cur = buckets[n];
while (cur != last) {
node* next = cur->next;
delete_node(cur);
cur = next;
buckets[n] = cur;
--num_elements;
}
} // 清空hashtable, 但是不释放vector的内存
template <class V, class K, class HF, class Ex, class Eq, class A>
void hashtable<V, K, HF, Ex, Eq, A>::clear()
{
for (size_type i = ; i < buckets.size(); ++i) {
node* cur = buckets[i];
while (cur != ) {
node* next = cur->next;
delete_node(cur);
cur = next;
}
buckets[i] = ;
}
num_elements = ;
} // 复制另一个hashtable给当前hashtable
template <class V, class K, class HF, class Ex, class Eq, class A>
void hashtable<V, K, HF, Ex, Eq, A>::copy_from(const hashtable& ht)
{
// 首先清空当前hashtable
buckets.clear();
// 预留足够容量
buckets.reserve(ht.buckets.size());
// 完成初始化操作, 这是hashtable的先验条件
buckets.insert(buckets.end(), ht.buckets.size(), (node*) );
__STL_TRY {
// 开始copy操作
for (size_type i = ; i < ht.buckets.size(); ++i) {
if (const node* cur = ht.buckets[i]) {
node* copy = new_node(cur->val);
buckets[i] = copy; for (node* next = cur->next; next; cur = next, next = cur->next) {
copy->next = new_node(next->val);
copy = copy->next;
}
}
}
num_elements = ht.num_elements;
}
__STL_UNWIND(clear());
} __STL_END_NAMESPACE #endif /* __SGI_STL_INTERNAL_HASHTABLE_H */ // Local Variables:
// mode:C++
// End:

stl_hashtable.h的更多相关文章

  1. STL源代码剖析 容器 stl_hashtable.h

    本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie hashtable ------------------------------------ ...

  2. stl_hash_set.h

    stl_hash_set.h // Filename: stl_hash_set.h // Comment By: 凝霜 // E-mail: mdl2009@vip.qq.com // Blog: ...

  3. stl_hash_map.h

    stl_hash_map.h // Filename: stl_hash_map.h // Comment By: 凝霜 // E-mail: mdl2009@vip.qq.com // Blog: ...

  4. STL源码剖析——hashtable

    二叉搜索树具有对数时间的搜索复杂度,但是这样的复杂度是再输入数据有足够的随机性的假设上哈希表在插入删除搜索操作上也具有常数时间的表现,而且这种表现是以统计为基础,不需要依赖输入元素的随机性 hasht ...

  5. STL之hashtable源代码剖析

    // Filename: stl_hashtable.h /////////////////////////////////////////////////////////////////////// ...

  6. C++ STL源码剖析

    stl_config.h defalloc.h stl_alloc.h memory.cpp stl_construct.h stl_uninitialized.h stl_iterator.h ty ...

  7. STL 之 hash_map源代码剖析

    // Filename: stl_hash_map.h // hash_map和hash_multimap是对hashtable的简单包装, 非常easy理解 /* * Copyright (c) 1 ...

  8. APUE中fcntl.h的使用及O_SYNC在Mac与Ubuntu下的测试

    此部分测试涉及到APUE V3中,第三章的图3-12到图3-14. 通过fcntl.h提供的功能,修改fd的文件属性,本处增加O_SYNC功能,并测试其效果. 本文涉及代码: tree ch3 ch3 ...

  9. 关于apue.3e中apue.h的使用

    关于apue.3e中apue.h的使用 近来要学一遍APUE第三版,并于此开博做为记录. 先下载源文件: # url: http://http//www.apuebook.com/code3e.htm ...

随机推荐

  1. linux 改动时间和日期date

    查看日期和时间 date 改动日期 date -s 月/日/年 date -s 08/15/2015 改动时间 date -s 09:29:33 写入CMOS sudo clock -w 利用ssh同 ...

  2. github常见错误

    如果输入$ Git remote add origin git@github.com:djqiang(github帐号名)/gitdemo(项目名).git 提示出错信息:fatal: remote ...

  3. vim对光标所在的数字进行增减

    真是vim会在不经意间给你惊喜...... 现在发现把光标移到某数字的上方,c-a是加1, c-x是减1 当时真有点众里寻他千百度的感觉

  4. This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its 错误解决办法

    This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary log ...

  5. centos7 运行postgres 数据库脚本db.sql

    [root@localhost ~]# su postgresbash-4.2$ psqlcould not change directory to "/root": Permis ...

  6. 11.23 Eclipse

    一.Eclipse Workspace File-->Switch Workspace 编译环境:Window -- Preferences – Java - Compiler 运行环境:Win ...

  7. where find

    where查询不到返回ActiveRecord::Relation [] find返回异常ActiveRecord::RecordNotFound: Couldn't find  where 查到返回 ...

  8. JQuery 双击动态编辑

             $(this).append(input);            $("input#temp").focus();            $("inp ...

  9. HDU - 5550 Game Rooms 【DP+前缀和】

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5550 题意 一撞大楼有N层楼,然后每层楼都有一部分人喜欢打羽毛球,一部分人喜欢打乒乓球 但是每层楼只能 ...

  10. PAT 天梯赛 L2-014. 列车调度 【队列】

    题目链接 https://www.patest.cn/contests/gplt/L2-014 思路 其实 每条火车道 都可以视为一个队列 满足队列的性质 当已经存在的队列 中 的列车序号 都小于 当 ...