STL之hashtable源码剖析

来源:互联网 发布:ubuntu安装fcitx五笔 编辑:程序博客网 时间:2024/04/30 23:56
// 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, 默认alloctemplate <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_SPECIALIZATIONtemplate <class V, class K, class HF, class ExK, class EqK, class All>inline forward_iterator_tagiterator_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_tagiterator_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_ORDERtemplate <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>::iteratorhashtable<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>::referencehashtable<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_typehashtable<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 voidhashtable<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 voidhashtable<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>voidhashtable<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给当前hashtabletemplate <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:

0 0
原创粉丝点击