// Filename:    stl_hashtable.h

////////////////////////////////////////////////////////////////////////////////
// 本实作的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_set, 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 = 28;
static const unsigned long __stl_prime_list[__stl_num_primes] =
{
53, 97, 193, 389, 769,
1543, 3079, 6151, 12289, 24593,
49157, 98317, 196613, 393241, 786433,
1572869, 3145739, 6291469, 12582917, 25165843,
50331653, 100663319, 201326611, 402653189, 805306457,
1610612741, 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 - 1) : *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(0)
{
initialize_buckets(n);
} hashtable(size_type n,
const HashFcn& hf,
const EqualKey& eql)
: hash(hf), equals(eql), get_key(ExtractKey()), num_elements(0)
{
initialize_buckets(n);
} hashtable(const hashtable& ht)
: hash(ht.hash), equals(ht.equals), get_key(ht.get_key), num_elements(0)
{
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(-1); }
bool empty() const { return size() == 0; } 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 = 0; n < buckets.size(); ++n)
if (buckets[n])
return iterator(buckets[n], this);
return end();
} iterator end() { return iterator(0, this); } const_iterator begin() const
{
for (size_type n = 0; n < buckets.size(); ++n)
if (buckets[n])
return const_iterator(buckets[n], this);
return end();
} const_iterator end() const { return const_iterator(0, 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 - 1]; } // 返回指定key映射了多少value
size_type elems_in_bucket(size_type bucket) const
{
size_type result = 0;
for (node* cur = buckets[bucket]; cur; cur = cur->next)
result += 1;
return result;
} // 插入操作, 不同意反复
pair<iterator, bool> insert_unique(const value_type& obj)
{
// 首先推断容量是否够用, 否则就又一次配置
resize(num_elements + 1);
return insert_unique_noresize(obj);
} // 插入操作, 同意反复
iterator insert_equal(const value_type& obj)
{
resize(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_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 = 0;
distance(f, l, n);
resize(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(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(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(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(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(num_elements + n);
for ( ; n > 0; --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 = 0; 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*) 0);
num_elements = 0;
} 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 = 0;
__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*) 0;
} 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*) 0;
} 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*) 0;
} 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*) 0;
} #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 = 0; 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 + 1); 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 + 1; 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 + 1; 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 = 0; // 開始查找并删除
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, 0);
for (size_type n = f_bucket + 1; n < l_bucket; ++n)
erase_bucket(n, 0);
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*) 0);
__STL_TRY {
// 先面開始copy
for (size_type bucket = 0; 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 = 0; 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 = 0; i < buckets.size(); ++i) {
node* cur = buckets[i];
while (cur != 0) {
node* next = cur->next;
delete_node(cur);
cur = next;
}
buckets[i] = 0;
}
num_elements = 0;
} // 复制还有一个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*) 0);
__STL_TRY {
// 開始copy操作
for (size_type i = 0; 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源代码剖析的更多相关文章

  1. 【Java集合源代码剖析】Hashtable源代码剖析

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/36191279 Hashtable简单介绍 Hashtable相同是基于哈希表实现的,相同每 ...

  2. HashTable源代码剖析

    <span style="font-size:14px;font-weight: normal;">public class Hashtable<K,V> ...

  3. STL 之 hash_map源代码剖析

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

  4. 【Java收集的源代码分析】Hashtable源代码分析

    Hashtable简单介绍 Hashtable相同是基于哈希表实现的,相同每一个元素是一个key-value对,其内部也是通过单链表解决冲突问题,容量不足(超过了阀值)时.相同会自己主动增长. Has ...

  5. STL源代码剖析 读书总结

    <<STL源代码剖析>> 侯捷著 非常早就买了这本书, 一直没看, 如今在实验室师兄代码的时候发现里面使用了大量泛型编程的内容, 让我有了先看看这本书的想法. 看之前我对于泛型 ...

  6. STL源代码剖析(一) - 内存分配

    Allocaor allocator 指的是空间配置器,用于分配内存.STL中默认使用SGI STL alloc作为STL的内存分配器,尽管未能符合标准规格,但效率上更好.SGI STL也定义有一个符 ...

  7. Java集合源代码剖析(二)【HashMap、Hashtable】

    HashMap源代码剖析 ; // 最大容量(必须是2的幂且小于2的30次方.传入容量过大将被这个值替换) static final int MAXIMUM_CAPACITY = 1 << ...

  8. STL源代码剖析——STL算法stl_algo.h

    前言 在前面的博文中剖析了STL的数值算法.基本算法和set集合算法.本文剖析STL其它的算法,比如排序算法.合并算法.查找算法等等.在剖析的时候.会针对函数给出一些样例说明函数的使用.源代码出自SG ...

  9. STL源代码剖析——基本算法stl_algobase.h

    前言 在STL中.算法是常常被使用的,算法在整个STL中起到很关键的数据.本节介绍的是一些基本算法,包括equal.fill.fill_n,iter_swap.lexicographical_comp ...

随机推荐

  1. 【BZOJ 4027】 4027: [HEOI2015]兔子与樱花 (贪心)

    4027: [HEOI2015]兔子与樱花 Description 很久很久之前,森林里住着一群兔子.有一天,兔子们突然决定要去看樱花.兔子们所在森林里的樱花树很特殊.樱花树由n个树枝分叉点组成,编号 ...

  2. 【UOJ #112】【APIO 2015】Palembang Bridges

    http://uoj.ac/problem/112 先扣掉在同一侧的情况. 当\(k=1\)时,桥建在所有位置的中位数. 当\(k=2\)时,对于每个居民\((S_i,T_i)\),这个居民只会走离\ ...

  3. python开发_python中的Boolean运算和真假值

    python中的真假值: Truth Value Testing Any object can be tested for truth value, for use in an if or while ...

  4. HDU 5653 Bomber Man wants to bomb an Array. dp

    Bomber Man wants to bomb an Array. 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5653 Description ...

  5. python画激活函数图像

    导入必要的库 import math import matplotlib.pyplot as plt import numpy as np import matplotlib as mpl mpl.r ...

  6. axios 与 Jquery-ajax 的使用区别

    axios 和 ajax 的使用方法基本一样,只有个别参数不同: 附:axios 中文文档 一.axios axios({ url: 'http://jsonplaceholder.typicode. ...

  7. Linux下同一网段内的IP中两台主机通信不经过路由器(ARP)(转)

    答案一:同一网段A与B通信,不需要路由器介入. A直接广播ARP request 到广播域,B处于同一广播域,可以接收到ARP request,B用单播方式直接告诉A自己的MAC B 地址.A收到B的 ...

  8. PEM DAC note

    开发指南V1.0库函数版本,PWM DAC实验 350页 STM32 的定时器最快的计数频率是72Mhz,8 为分辨率的时候,PWM 频率为72M/256=281.25Khz.如果是1阶RC滤波,则要 ...

  9. WinForm中DataGridView验证单元格输入的是数字

    转载:http://www.cnblogs.com/ganqiyin/archive/2013/02/18/2915491.html 事件:DataGridView验证单元格输入的是数字,DataGr ...

  10. Silverlight:《Pro Silverlight5》读书笔记 之 XAML

    XAML Properties and Events in XAML Simple Properties and Type Converters To bridge the gap between s ...