stl_hashtable.h
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的更多相关文章
- STL源代码剖析 容器 stl_hashtable.h
本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie hashtable ------------------------------------ ...
- stl_hash_set.h
stl_hash_set.h // Filename: stl_hash_set.h // Comment By: 凝霜 // E-mail: mdl2009@vip.qq.com // Blog: ...
- stl_hash_map.h
stl_hash_map.h // Filename: stl_hash_map.h // Comment By: 凝霜 // E-mail: mdl2009@vip.qq.com // Blog: ...
- STL源码剖析——hashtable
二叉搜索树具有对数时间的搜索复杂度,但是这样的复杂度是再输入数据有足够的随机性的假设上哈希表在插入删除搜索操作上也具有常数时间的表现,而且这种表现是以统计为基础,不需要依赖输入元素的随机性 hasht ...
- STL之hashtable源代码剖析
// Filename: stl_hashtable.h /////////////////////////////////////////////////////////////////////// ...
- C++ STL源码剖析
stl_config.h defalloc.h stl_alloc.h memory.cpp stl_construct.h stl_uninitialized.h stl_iterator.h ty ...
- STL 之 hash_map源代码剖析
// Filename: stl_hash_map.h // hash_map和hash_multimap是对hashtable的简单包装, 非常easy理解 /* * Copyright (c) 1 ...
- APUE中fcntl.h的使用及O_SYNC在Mac与Ubuntu下的测试
此部分测试涉及到APUE V3中,第三章的图3-12到图3-14. 通过fcntl.h提供的功能,修改fd的文件属性,本处增加O_SYNC功能,并测试其效果. 本文涉及代码: tree ch3 ch3 ...
- 关于apue.3e中apue.h的使用
关于apue.3e中apue.h的使用 近来要学一遍APUE第三版,并于此开博做为记录. 先下载源文件: # url: http://http//www.apuebook.com/code3e.htm ...
随机推荐
- 【入门】创建express项目
1.创建项目(图解) 2.访问http://localhost:3000/就看到熟悉的页面了 3.查看项目目录 参考文档:http://jingyan.baidu.com/article/92 ...
- 数字证书转换cer---pem
下载openssl-1.0.1s 安装好openssl之后,进入openssl目录: 输入openssl命令,即进入命令模式: 先将要转换的cer证书也放到openssl目录下面,然后执行以下 ...
- 【iOS开发-80】Quartz2D绘图简介:直线/圆形/椭圆/方形以及上下文栈管理CGContextSaveGState/CGContextRestoreGState
本文转载至 http://blog.csdn.net/weisubao/article/details/41282457 - (void)drawRect:(CGRect)rect { //获得当前上 ...
- OKR与KPI管理的区别与联系
OKR是一种新兴的管理体系,最近几年被引进中国.由于在IT.互联网.金融.游戏等知识密集型企业中有着显著的效果,得到中国企业的认可. OKR是英文Objectives & Key Result ...
- Cow Contest(传递闭包)
Cow Contest Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10450 Accepted: 5841 Desc ...
- 九度OJ 1195:最长&最短文本 (搜索)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:3144 解决:1156 题目描述: 输入多行字符串,请按照原文本中的顺序输出其中最短和最长的字符串,如果最短和最长的字符串不止一个,请全部输 ...
- [Errno 14] PYCURL ERROR 7 - "couldn't connect to host"
该问题就是防火墙的问题.关闭即可. /etc/init.d/iptables stop
- php在不同平台下路径分隔符不同的解决办法
在看phpamf时看到一个常量“DIRECTORY_SEPARATOR”,最后发现是一个全局的常量,用来定义路径分隔符的 主要解决在windows和linux下路径分隔符不同的造成代码不通用的问题,在 ...
- [原创]java WEB学习笔记13:JSP介绍(背景,特点,原理)
JSP介绍:(理解) 1)JSP背景 ①在很多动态网页中,绝大部分内容都是固定不变的,只有局部内容需要动态产生和改变: ②如果使用Servlet程序来输出只有局部内容需要动态改变的网页,其中所有的静态 ...
- nginx日志配置,以及日志轮询
一.为nginx配置错误日志 Nginx错误日志是调试nginx的重要手段,属于核心功能模块的参数(ngx_core_module)该参数名字为err_log,是放在Main区块中全局配置 err_l ...