zoukankan      html  css  js  c++  java
  • STL之hashtable源代码剖析

    // 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:


  • 相关阅读:
    【转】解决在Android设备播放音频与其他应用重音的问题,并监听耳机的控制按钮
    【转】wamp 3.0.6(apache 2.4.23) 403 forbidden 解决办法
    身份证第18位(校验码)的计算方法
    【转】Win10开机密码忘了?教你破解Win10开机密码
    【转】具透 | 你可能不知道,iOS 10 有一个中国「特供」的联网权限功能
    钉钉自定义机器人 发送文本 换行 无效果
    屏蔽右键+f12
    【转】理解WebKit和Chromium: JavaScript引擎简介
    第2章 排序 | 第10节 计数排序练习题 && 基数排序
    图像处理-深入探索插值操作
  • 原文地址:https://www.cnblogs.com/brucemengbm/p/7326984.html
Copyright © 2011-2022 走看看