《STL源码剖析》---stl_hashtable.h阅读笔记

在前面介绍的RB-tree红黑树中,可以看出红黑树的插入、查找、删除的平均时间复杂度为O(nlogn)。但这是基于一个假设:输入数据具有随机性。而哈希表/散列表hash table在插入、删除、查找上具有“平均常数时间复杂度”O(1);且不依赖输入数据的随机性。

hash table的实现有线性探测、二次探测、二次散列等实现,SGI的STL是采用开链法(separate chaining)来实现的。大概原理就是在hash table的每一项都是个指针(指向一个链表),叫做bucket。这样的话如果多个key值散列到同一位置,那么就存储到这个位置对应的链表中。如下图所示:

hash table使用了vector来做buckets的容器,容器大小是质数(因为散列函数好多情况下是取余数),实现代码如下:

[cpp]  view plain  copy
  1. G++ 2.91.57,cygnus\cygwin-b20\include\g++\stl_hashtable.h 完整列表  
  2. /* 
  3.  * Copyright (c) 1996,1997 
  4.  * Silicon Graphics Computer Systems, Inc. 
  5.  * 
  6.  * Permission to use, copy, modify, distribute and sell this software 
  7.  * and its documentation for any purpose is hereby granted without fee, 
  8.  * provided that the above copyright notice appear in all copies and 
  9.  * that both that copyright notice and this permission notice appear 
  10.  * in supporting documentation.  Silicon Graphics makes no 
  11.  * representations about the suitability of this software for any 
  12.  * purpose.  It is provided "as is" without express or implied warranty. 
  13.  * 
  14.  * 
  15.  * Copyright (c) 1994 
  16.  * Hewlett-Packard Company 
  17.  * 
  18.  * Permission to use, copy, modify, distribute and sell this software 
  19.  * and its documentation for any purpose is hereby granted without fee, 
  20.  * provided that the above copyright notice appear in all copies and 
  21.  * that both that copyright notice and this permission notice appear 
  22.  * in supporting documentation.  Hewlett-Packard Company makes no 
  23.  * representations about the suitability of this software for any 
  24.  * purpose.  It is provided "as is" without express or implied warranty. 
  25.  * 
  26.  */  
  27.   
  28. /* NOTE: This is an internal header file, included by other STL headers. 
  29.  *   You should not attempt to use it directly. 
  30.  */  
  31.   
  32. #ifndef __SGI_STL_INTERNAL_HASHTABLE_H  
  33. #define __SGI_STL_INTERNAL_HASHTABLE_H  
  34.   
  35. // Hashtable class 用來實作 hashed associative containers  
  36. // hash_set, hash_map, hash_multiset, 和 hash_multimap.  
  37.   
  38. #include <stl_algobase.h>  
  39. #include <stl_alloc.h>  
  40. #include <stl_construct.h>  
  41. #include <stl_tempbuf.h>  
  42. #include <stl_algo.h>  
  43. #include <stl_uninitialized.h>  
  44. #include <stl_function.h>  
  45. #include <stl_vector.h>  
  46. #include <stl_hash_fun.h>  
  47.   
  48. __STL_BEGIN_NAMESPACE  
  49. //hash table中节点的定义,都是public  
  50. template <class Value>  
  51. struct __hashtable_node  
  52. {  
  53.  /* 
  54.     用vector来做hash table,为什么还需要next指针? 
  55.     因为SGI 实现的hash table使用了开链法/链接法。 
  56.     hash table中的节点可能代表一系列节点。它们以链形式连接。 
  57.     这是所谓的 separate chaining 技巧。 
  58.  */  
  59.   __hashtable_node* next;     
  60.   Value val;  
  61. };    
  62. //先声明 hash table,在 iterator中有用到。  
  63. template <class Value, class Key, class HashFcn,  
  64.           class ExtractKey, class EqualKey, class Alloc = alloc>  
  65. class hashtable;  
  66.   
  67. // 由与 __hashtable_iterator 和 __hashtable_const_iterator 两者会  
  68. // 互相使用,因此必须在下面先做声明,否则编译出错。  
  69. template <class Value, class Key, class HashFcn,  
  70.           class ExtractKey, class EqualKey, class Alloc>  
  71. struct __hashtable_iterator;  
  72.   
  73. template <class Value, class Key, class HashFcn,  
  74.           class ExtractKey, class EqualKey, class Alloc>  
  75. struct __hashtable_const_iterator;  
  76.   
  77. //hash table中的迭代器  
  78. template <class Value, class Key, class HashFcn,  
  79.           class ExtractKey, class EqualKey, class Alloc>  
  80. struct __hashtable_iterator {  
  81.   typedef hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>  
  82.           hashtable;  
  83.   typedef __hashtable_iterator<Value, Key, HashFcn,   
  84.                                ExtractKey, EqualKey, Alloc>  
  85.           iterator;  
  86.   typedef __hashtable_const_iterator<Value, Key, HashFcn,   
  87.                                      ExtractKey, EqualKey, Alloc>  
  88.           const_iterator;  
  89.   typedef __hashtable_node<Value> node;  
  90.   
  91.   //迭代器类型,只能向前  
  92.   typedef forward_iterator_tag iterator_category;  
  93.   typedef Value value_type;  
  94.   typedef ptrdiff_t difference_type;  
  95.   typedef size_t size_type;  
  96.   typedef Value& reference;  
  97.   typedef Value* pointer;  
  98.   
  99.   node* cur;        // 迭代器目前所指之节点  
  100.   hashtable* ht;    // 保持对容器的连接关系,因为可能需要从bucket跳到bucket  
  101.   
  102.   __hashtable_iterator(node* n, hashtable* tab) : cur(n), ht(tab) {}  
  103.   //默认构造函数什么也没做  
  104.   __hashtable_iterator() {}  
  105.   reference operator*() const { return cur->val; }  
  106. #ifndef __SGI_STL_NO_ARROW_OPERATOR  
  107.   pointer operator->() const { return &(operator*()); }  
  108. #endif /* __SGI_STL_NO_ARROW_OPERATOR */  
  109.   iterator& operator++();  
  110.   iterator operator++(int);  
  111.   bool operator==(const iterator& it) const { return cur == it.cur; }  
  112.   bool operator!=(const iterator& it) const { return cur != it.cur; }  
  113. };  
  114.   
  115.   
  116. template <class Value, class Key, class HashFcn,  
  117.           class ExtractKey, class EqualKey, class Alloc>  
  118. struct __hashtable_const_iterator {  
  119.   typedef hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>  
  120.           hashtable;  
  121.   typedef __hashtable_iterator<Value, Key, HashFcn,   
  122.                                ExtractKey, EqualKey, Alloc>  
  123.           iterator;  
  124.   typedef __hashtable_const_iterator<Value, Key, HashFcn,   
  125.                                      ExtractKey, EqualKey, Alloc>  
  126.           const_iterator;  
  127.   typedef __hashtable_node<Value> node;  
  128.   
  129.   typedef forward_iterator_tag iterator_category;   // 注意  
  130.   typedef Value value_type;  
  131.   typedef ptrdiff_t difference_type;  
  132.   typedef size_t size_type;  
  133.   typedef const Value& reference;  
  134.   typedef const Value* pointer;  
  135.   
  136.   const node* cur;  
  137.   const hashtable* ht;  
  138.   
  139.   __hashtable_const_iterator(const node* n, const hashtable* tab)  
  140.     : cur(n), ht(tab) {}  
  141.   __hashtable_const_iterator() {}  
  142.   __hashtable_const_iterator(const iterator& it) : cur(it.cur), ht(it.ht) {}  
  143.   reference operator*() const { return cur->val; }  
  144. #ifndef __SGI_STL_NO_ARROW_OPERATOR  
  145.   pointer operator->() const { return &(operator*()); }  
  146. #endif /* __SGI_STL_NO_ARROW_OPERATOR */  
  147.   const_iterator& operator++();  
  148.   const_iterator operator++(int);  
  149.   bool operator==(const const_iterator& it) const { return cur == it.cur; }  
  150.   bool operator!=(const const_iterator& it) const { return cur != it.cur; }  
  151. };  
  152.   
  153. // 注意:假设 long 至少有 32 bits。  
  154. //定义28个素数(大概是2倍关系增长),用来做hash table的大小  
  155. static const int __stl_num_primes = 28;  
  156. static const unsigned long __stl_prime_list[__stl_num_primes] =  
  157. {  
  158.   53,         97,           193,         389,       769,  
  159.   1543,       3079,         6151,        12289,     24593,  
  160.   49157,      98317,        196613,      393241,    786433,  
  161.   1572869,    3145739,      6291469,     12582917,  25165843,  
  162.   50331653,   100663319,    201326611,   402653189, 805306457,   
  163.   1610612741, 3221225473ul, 4294967291ul  
  164. };  
  165.   
  166. //找出28个素数中,最接近n且大于n的那个数  
  167. inline unsigned long __stl_next_prime(unsigned long n)  
  168. {  
  169.   const unsigned long* first = __stl_prime_list;  
  170.   const unsigned long* last = __stl_prime_list + __stl_num_primes;  
  171.   const unsigned long* pos = lower_bound(first, last, n);  
  172.   // 以上,lower_bound() 是泛型算法  
  173.   // 使用 lower_bound(),序列需先排序。上述数组以排序  
  174.   return pos == last ? *(last - 1) : *pos;  
  175. }  
  176. /* 
  177. Value 节点的实值类型 
  178. Key   节点的键值类型 
  179. HashFcn hash function的类型 
  180. EqualKey从节点中取出键值的方法(函数或仿函数) 
  181. EqualKey判断键值是否相同的方法(函数或仿函数) 
  182. */  
  183. template <class Value, class Key, class HashFcn,  
  184.           class ExtractKey, class EqualKey,  
  185.           class Alloc>   // 最上面已经说明:默认使用 alloc 空间配置器。  
  186. class hashtable {  
  187. public:  
  188.   //为 template  类型参数重新定义一个名称(貌似没必要)  
  189.   typedef Key key_type;  
  190.   typedef Value value_type;  
  191.   typedef HashFcn hasher;//hash函数  
  192.   typedef EqualKey key_equal;  
  193.   
  194.   typedef size_t            size_type;  
  195.   typedef ptrdiff_t         difference_type;  
  196.   typedef value_type*       pointer;  
  197.   typedef const value_type* const_pointer;  
  198.   typedef value_type&       reference;  
  199.   typedef const value_type& const_reference;  
  200.   
  201.   hasher hash_funct() const { return hash; }  
  202.   key_equal key_eq() const { return equals; }  
  203.   
  204. private:  
  205.   //以下三个都是 function objects。。、<stl_hash_fun.h>中定义了几个  
  206.   //标准类型(如int,c-style string等)的 hasher。  
  207.   hasher hash;    
  208.   key_equal equals;  
  209.   ExtractKey get_key;  
  210.   
  211.   typedef __hashtable_node<Value> node;  
  212.   typedef simple_alloc<node, Alloc> node_allocator;  
  213.   
  214.   vector<node*,Alloc> buckets;    // 以 vector 完成  
  215.   size_type num_elements;//hash table中节点的个数  
  216.   
  217. public:  
  218.   typedef __hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey,   
  219.                                Alloc>  
  220.   iterator;  
  221.   
  222.   typedef __hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey,  
  223.                                      Alloc>  
  224.   const_iterator;  
  225.   
  226.   friend struct  
  227.   __hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>;  
  228.   friend struct  
  229.   __hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>;  
  230.   
  231. public:  
  232.   //没有默认的构造函数  
  233.   hashtable(size_type n,  
  234.             const HashFcn&    hf,  
  235.             const EqualKey&   eql,  
  236.             const ExtractKey& ext)  
  237.     : hash(hf), equals(eql), get_key(ext), num_elements(0)  
  238.   {  
  239.     initialize_buckets(n);  
  240.   }  
  241.   
  242.   hashtable(size_type n,  
  243.             const HashFcn&    hf,  
  244.             const EqualKey&   eql)  
  245.     : hash(hf), equals(eql), get_key(ExtractKey()), num_elements(0)  
  246.   {  
  247.     initialize_buckets(n);  
  248.   }  
  249.   
  250.   hashtable(const hashtable& ht)  
  251.     : hash(ht.hash), equals(ht.equals), get_key(ht.get_key), num_elements(0)  
  252.   {  
  253.     copy_from(ht);  
  254.   }  
  255.   
  256.   hashtable& operator= (const hashtable& ht)  
  257.   {  
  258.     if (&ht != this) {  //防止自身赋值  
  259.       clear();      // 先清除自己  
  260.       hash = ht.hash;   // 以下三个动作,将三份data members 复制过来。  
  261.       equals = ht.equals;  
  262.       get_key = ht.get_key;  
  263.       copy_from(ht);    // 完整赋值整个 hash table的内容。  
  264.     }  
  265.     return *this;  
  266.   }  
  267.   
  268.   ~hashtable() { clear(); }  
  269.   
  270.   size_type size() const { return num_elements; }  
  271.   size_type max_size() const { return size_type(-1); }  
  272.   bool empty() const { return size() == 0; }  
  273.   
  274.   void swap(hashtable& ht)  
  275.   {  
  276.     __STD::swap(hash, ht.hash);  
  277.     __STD::swap(equals, ht.equals);  
  278.     __STD::swap(get_key, ht.get_key);  
  279.     buckets.swap(ht.buckets);  
  280.     __STD::swap(num_elements, ht.num_elements);  
  281.   }  
  282.   
  283.   iterator begin()  
  284.   {   
  285.     for (size_type n = 0; n < buckets.size(); ++n)  
  286.       //找出第一个被使用的节点,此即 begin iterator。  
  287.       if (buckets[n])  
  288.         return iterator(buckets[n], this);  
  289.     return end();  
  290.   }  
  291.   
  292.   //最后被使用节点的下个位置,所以使用0来初始化迭代器  
  293.   iterator end() { return iterator(0, this); }  
  294.   
  295.   const_iterator begin() const  
  296.   {  
  297.     for (size_type n = 0; n < buckets.size(); ++n)  
  298.       if (buckets[n])  
  299.         return const_iterator(buckets[n], this);  
  300.     return end();  
  301.   }  
  302.   
  303.   const_iterator end() const { return const_iterator(0, this); }  
  304.   
  305.   friend bool  
  306.   operator== __STL_NULL_TMPL_ARGS (const hashtable&, const hashtable&);  
  307.   
  308. public:  
  309.   
  310.   // bucket 个数即 buckets vector 的大小  
  311.   size_type bucket_count() const { return buckets.size(); }  
  312.   
  313.   //以目前情况(不重建表格),总共可以有多少个 buckets  
  314.   size_type max_bucket_count() const  
  315.     { return __stl_prime_list[__stl_num_primes - 1]; }   
  316.   
  317.   // 某一个 bucket (内含一个list) 容纳多少个元素  
  318.   size_type elems_in_bucket(size_type bucket) const  
  319.   {  
  320.     size_type result = 0;  
  321.     for (node* cur = buckets[bucket]; cur; cur = cur->next)  
  322.       result += 1;  
  323.     return result;  
  324.   }  
  325.   
  326.   //安插元素,不允许重复  
  327.   pair<iterator, bool> insert_unique(const value_type& obj)  
  328.   {  
  329.     resize(num_elements + 1);   // 判断是否需要重建表格,如果需要就填充  
  330.     return insert_unique_noresize(obj);  
  331.   }  
  332.   
  333.   // 安插元素,允许重复  
  334.   iterator insert_equal(const value_type& obj)  
  335.   {  
  336.     resize(num_elements + 1);  
  337.     return insert_equal_noresize(obj);  
  338.   }  
  339.   
  340.   pair<iterator, bool> insert_unique_noresize(const value_type& obj);  
  341.   iterator insert_equal_noresize(const value_type& obj);  
  342.    
  343. #ifdef __STL_MEMBER_TEMPLATES  
  344. //插入两个迭代器之间的元素[f l)  
  345.   template <class InputIterator>  
  346.   void insert_unique(InputIterator f, InputIterator l)  
  347.   {  
  348.     insert_unique(f, l, iterator_category(f));  
  349.   }  
  350.   
  351.   template <class InputIterator>  
  352.   void insert_equal(InputIterator f, InputIterator l)  
  353.   {  
  354.     insert_equal(f, l, iterator_category(f));  
  355.   }  
  356.   
  357.   template <class InputIterator>  
  358.   void insert_unique(InputIterator f, InputIterator l,  
  359.                      input_iterator_tag)  
  360.   {  
  361.     for ( ; f != l; ++f)  
  362.       insert_unique(*f);  
  363.   }  
  364.   
  365.   template <class InputIterator>  
  366.   void insert_equal(InputIterator f, InputIterator l,  
  367.                     input_iterator_tag)  
  368.   {  
  369.     for ( ; f != l; ++f)  
  370.       insert_equal(*f);  
  371.   }  
  372.   
  373.   template <class ForwardIterator>  
  374.   void insert_unique(ForwardIterator f, ForwardIterator l,  
  375.                      forward_iterator_tag)  
  376.   {  
  377.     size_type n = 0;  
  378.     distance(f, l, n);//判断两个迭代器的距离,n是引用传递  
  379.     resize(num_elements + n);       // 判断(并实施)表格的重建  
  380.     for ( ; n > 0; --n, ++f)  
  381.       insert_unique_noresize(*f);   // 一一安插新元素  
  382.   }  
  383.   
  384.   template <class ForwardIterator>  
  385.   void insert_equal(ForwardIterator f, ForwardIterator l,  
  386.                     forward_iterator_tag)  
  387.   {  
  388.     size_type n = 0;  
  389.     distance(f, l, n);  
  390.     resize(num_elements + n);  
  391.     for ( ; n > 0; --n, ++f)  
  392.       insert_equal_noresize(*f);        // 一一安插新元素  
  393.   }  
  394.   
  395. #else /* __STL_MEMBER_TEMPLATES */  
  396.   void insert_unique(const value_type* f, const value_type* l)  
  397.   {  
  398.   //可以直接计算迭代器之间的距离,应该是rando access iterator  
  399.     size_type n = l - f;  
  400.     resize(num_elements + n);  
  401.     for ( ; n > 0; --n, ++f)  
  402.       insert_unique_noresize(*f);  
  403.   }  
  404.   
  405.   void insert_equal(const value_type* f, const value_type* l)  
  406.   {  
  407.     size_type n = l - f;  
  408.     resize(num_elements + n);  
  409.     for ( ; n > 0; --n, ++f)  
  410.       insert_equal_noresize(*f);  
  411.   }  
  412.   
  413.   void insert_unique(const_iterator f, const_iterator l)  
  414.   {  
  415.     size_type n = 0;  
  416.     distance(f, l, n);  
  417.     resize(num_elements + n);  
  418.     for ( ; n > 0; --n, ++f)  
  419.       insert_unique_noresize(*f);  
  420.   }  
  421.   
  422.   void insert_equal(const_iterator f, const_iterator l)  
  423.   {  
  424.     size_type n = 0;  
  425.     distance(f, l, n);  
  426.     resize(num_elements + n);  
  427.     for ( ; n > 0; --n, ++f)  
  428.       insert_equal_noresize(*f);  
  429.   }  
  430. #endif /*__STL_MEMBER_TEMPLATES */  
  431.   
  432.   reference find_or_insert(const value_type& obj);  
  433.   
  434.   iterator find(const key_type& key)   
  435.   {  
  436.     size_type n = bkt_num_key(key); // 首先找到落在哪个bucket内  
  437.     node* first;  
  438.     //从bucket list的头开始,一一对比每个元素的键值。  
  439.     for ( first = buckets[n];     
  440.           first && !equals(get_key(first->val), key);  
  441.           first = first->next)  
  442.       {}  
  443.     return iterator(first, this);  
  444.   }   
  445.   
  446.   const_iterator find(const key_type& key) const  
  447.   {  
  448.     size_type n = bkt_num_key(key);  
  449.     const node* first;  
  450.     for ( first = buckets[n];  
  451.           first && !equals(get_key(first->val), key);  
  452.           first = first->next)  
  453.       {}  
  454.     return const_iterator(first, this);  
  455.   }   
  456.   
  457.   //查看hash table中含有多少个值为key的元素  
  458.   size_type count(const key_type& key) const  
  459.   {  
  460.     const size_type n = bkt_num_key(key);  
  461.     size_type result = 0;  
  462.   
  463.     // 以下,从bucket list 的头开始,一一比对每个素的键值。比对成功就累加1。  
  464.     for (const node* cur = buckets[n]; cur; cur = cur->next)  
  465.       if (equals(get_key(cur->val), key))  
  466.         ++result;  
  467.     return result;  
  468.   }  
  469.   
  470.   pair<iterator, iterator> equal_range(const key_type& key);  
  471.   pair<const_iterator, const_iterator> equal_range(const key_type& key) const;  
  472.   
  473.   size_type erase(const key_type& key);  
  474.   void erase(const iterator& it);  
  475.   void erase(iterator first, iterator last);  
  476.   
  477.   void erase(const const_iterator& it);  
  478.   void erase(const_iterator first, const_iterator last);  
  479.   
  480.   void resize(size_type num_elements_hint);  
  481.   void clear();  
  482.   
  483. private:  
  484.   // 寻找STL中提供的下一个质数  
  485.   size_type next_size(size_type n) const { return __stl_next_prime(n); }  
  486.   
  487.   // 注意,hash_vec 和 hash_map 都將其底層的 hash table 的初始大小預設為 100  
  488.   // hash_vec 和 hash_map 都将底层的 hash table初始化大小预设为100  
  489.   void initialize_buckets(size_type n)  
  490.   {  
  491.     //例如:传入100,返回193。以下首先保留193个元素空间,然后将其全部填0。  
  492.     //例如:传入50,返回53。以下首先保留53个元素空间,然后将其全部填0。  
  493.     const size_type n_buckets = next_size(n);   
  494.       
  495.     buckets.reserve(n_buckets);  
  496.     buckets.insert(buckets.end(), n_buckets, (node*) 0);  
  497.     num_elements = 0;  
  498.   }  
  499.   
  500.   size_type bkt_num_key(const key_type& key) const  
  501.   {  
  502.     return bkt_num_key(key, buckets.size());  
  503.   }  
  504.   
  505.   size_type bkt_num(const value_type& obj) const  
  506.   {  
  507.     return bkt_num_key(get_key(obj));  
  508.   }  
  509.   
  510.   size_type bkt_num_key(const key_type& key, size_t n) const  
  511.   {  
  512.     return hash(key) % n;  
  513.   }  
  514.   
  515.   size_type bkt_num(const value_type& obj, size_t n) const  
  516.   {  
  517.     return bkt_num_key(get_key(obj), n);  
  518.   }  
  519.   
  520.   node* new_node(const value_type& obj)  
  521.   {  
  522.     node* n = node_allocator::allocate();//配置空间  
  523.     n->next = 0;//指针next设置为NULL  
  524.     __STL_TRY {  
  525.       construct(&n->val, obj);//构建元素  
  526.       return n;  
  527.     }  
  528.     //commit or rollback  
  529.     __STL_UNWIND(node_allocator::deallocate(n));  
  530.   }  
  531.     
  532.   void delete_node(node* n)  
  533.   {  
  534.     destroy(&n->val);//析构  
  535.     node_allocator::deallocate(n);//释放空间  
  536.   }  
  537.   
  538.   void erase_bucket(const size_type n, node* first, node* last);  
  539.   void erase_bucket(const size_type n, node* last);  
  540.   
  541.   void copy_from(const hashtable& ht);  
  542.   
  543. };  
  544.   
  545. template <class V, class K, class HF, class ExK, class EqK, class A>  
  546. __hashtable_iterator<V, K, HF, ExK, EqK, A>&  
  547. __hashtable_iterator<V, K, HF, ExK, EqK, A>::operator++()  
  548. {  
  549.   const node* old = cur;  
  550.   cur = cur->next;   // 如果存在,就是它。否则进入以下 if 流程  
  551.   if (!cur) {  
  552.     // 根据原值,重新定位。从该位置(bucket)的下一个位置找起。  
  553.     size_type bucket = ht->bkt_num(old->val);  
  554.     while (!cur && ++bucket < ht->buckets.size()) // 注意,prefix operator++  
  555.       cur = ht->buckets[bucket];  
  556.   }  
  557.   return *this;  
  558. }  
  559.   
  560. template <class V, class K, class HF, class ExK, class EqK, class A>  
  561. inline __hashtable_iterator<V, K, HF, ExK, EqK, A>  
  562. __hashtable_iterator<V, K, HF, ExK, EqK, A>::operator++(int)  
  563. {  
  564.   iterator tmp = *this;  
  565.   ++*this;  // 调用 operator++()  
  566.   return tmp;  
  567. }  
  568.   
  569. template <class V, class K, class HF, class ExK, class EqK, class A>  
  570. __hashtable_const_iterator<V, K, HF, ExK, EqK, A>&  
  571. __hashtable_const_iterator<V, K, HF, ExK, EqK, A>::operator++()  
  572. {  
  573.   const node* old = cur;  
  574.   cur = cur->next;  
  575.   if (!cur) {  
  576.     size_type bucket = ht->bkt_num(old->val);  
  577.     while (!cur && ++bucket < ht->buckets.size())  
  578.       cur = ht->buckets[bucket];  
  579.   }  
  580.   return *this;  
  581. }  
  582.   
  583. template <class V, class K, class HF, class ExK, class EqK, class A>  
  584. inline __hashtable_const_iterator<V, K, HF, ExK, EqK, A>  
  585. __hashtable_const_iterator<V, K, HF, ExK, EqK, A>::operator++(int)  
  586. {  
  587.   const_iterator tmp = *this;  
  588.   ++*this;  
  589.   return tmp;  
  590. }  
  591.   
  592. #ifndef __STL_CLASS_PARTIAL_SPECIALIZATION  
  593.   
  594. template <class V, class K, class HF, class ExK, class EqK, class All>  
  595. inline forward_iterator_tag  
  596. iterator_category(const __hashtable_iterator<V, K, HF, ExK, EqK, All>&)  
  597. {  
  598.   return forward_iterator_tag();  
  599. }  
  600.   
  601. template <class V, class K, class HF, class ExK, class EqK, class All>  
  602. inline V* value_type(const __hashtable_iterator<V, K, HF, ExK, EqK, All>&)  
  603. {  
  604.   return (V*) 0;  
  605. }  
  606.   
  607. template <class V, class K, class HF, class ExK, class EqK, class All>  
  608. inline hashtable<V, K, HF, ExK, EqK, All>::difference_type*  
  609. distance_type(const __hashtable_iterator<V, K, HF, ExK, EqK, All>&)  
  610. {  
  611.   return (hashtable<V, K, HF, ExK, EqK, All>::difference_type*) 0;  
  612. }  
  613.   
  614. template <class V, class K, class HF, class ExK, class EqK, class All>  
  615. inline forward_iterator_tag  
  616. iterator_category(const __hashtable_const_iterator<V, K, HF, ExK, EqK, All>&)  
  617. {  
  618.   return forward_iterator_tag();  
  619. }  
  620.   
  621. template <class V, class K, class HF, class ExK, class EqK, class All>  
  622. inline V*   
  623. value_type(const __hashtable_const_iterator<V, K, HF, ExK, EqK, All>&)  
  624. {  
  625.   return (V*) 0;  
  626. }  
  627.   
  628. template <class V, class K, class HF, class ExK, class EqK, class All>  
  629. inline hashtable<V, K, HF, ExK, EqK, All>::difference_type*  
  630. distance_type(const __hashtable_const_iterator<V, K, HF, ExK, EqK, All>&)  
  631. {  
  632.   return (hashtable<V, K, HF, ExK, EqK, All>::difference_type*) 0;  
  633. }  
  634.   
  635. #endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */  
  636. //判断两个hash table是否相等(两个hasn table的 buckets相同,且  
  637. //bucket对应的list相同)  
  638. template <class V, class K, class HF, class Ex, class Eq, class A>  
  639. bool operator==(const hashtable<V, K, HF, Ex, Eq, A>& ht1,  
  640.                 const hashtable<V, K, HF, Ex, Eq, A>& ht2)  
  641. {  
  642.   typedef typename hashtable<V, K, HF, Ex, Eq, A>::node node;  
  643.   if (ht1.buckets.size() != ht2.buckets.size())  
  644.     return false;  
  645.   for (int n = 0; n < ht1.buckets.size(); ++n) {  
  646.     node* cur1 = ht1.buckets[n];  
  647.     node* cur2 = ht2.buckets[n];  
  648.     for ( ; cur1 && cur2 && cur1->val == cur2->val;  
  649.           cur1 = cur1->next, cur2 = cur2->next)  
  650.       {}  
  651.     if (cur1 || cur2)//如果cur1或cur2有一个不等于0(没有指向最后位置的下一个位置)  
  652.       return false;  
  653.   }  
  654.   return true;  
  655. }    
  656.   
  657. #ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER  
  658.   
  659. template <class Val, class Key, class HF, class Extract, class EqKey, class A>  
  660. inline void swap(hashtable<Val, Key, HF, Extract, EqKey, A>& ht1,  
  661.                  hashtable<Val, Key, HF, Extract, EqKey, A>& ht2) {  
  662.   ht1.swap(ht2);  
  663. }  
  664.   
  665. #endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */  
  666.   
  667. //在不重建表格的情况下安插新节点。键值不允许重复。返回pair。第二个参数指出  
  668. //插入是否成功  
  669. template <class V, class K, class HF, class Ex, class Eq, class A>  
  670. pair<typename hashtable<V, K, HF, Ex, Eq, A>::iterator, bool>   
  671. hashtable<V, K, HF, Ex, Eq, A>::insert_unique_noresize(const value_type& obj)  
  672. {  
  673.   const size_type n = bkt_num(obj); // 決定obj位于哪个buckets中  
  674.   node* first = buckets[n];  // 令 first 指向 bucket 对应串列头部  
  675.   
  676.   // 如果 buckets[n] 已被占用,此时first 将不为0,于是进入以下循环,  
  677.   // 遍历bucket对应的整个链表  
  678.   for (node* cur = first; cur; cur = cur->next)   
  679.     if (equals(get_key(cur->val), get_key(obj)))  
  680.       // 如果发现链表中的某键值相同,就不安插,立刻回返。  
  681.       return pair<iterator, bool>(iterator(cur, this), false);  
  682.   
  683.   //离开以上循环(或没进入循环),first指向指向bucket所指链表的头部节点  
  684.   node* tmp = new_node(obj);    // 生成新节点并赋值  
  685.   tmp->next = first;         //更改新节点指针  
  686.   buckets[n] = tmp;             // 新节点称为bucket链表第一个节点  
  687.   ++num_elements;               // 节点个诉累加1  
  688.   return pair<iterator, bool>(iterator(tmp, this), true);  
  689. }  
  690.   
  691. //在不重建表格的情况下安插新节点。键值不允许重复。  
  692. template <class V, class K, class HF, class Ex, class Eq, class A>  
  693. typename hashtable<V, K, HF, Ex, Eq, A>::iterator   
  694. hashtable<V, K, HF, Ex, Eq, A>::insert_equal_noresize(const value_type& obj)  
  695. {  
  696.   const size_type n = bkt_num(obj);   
  697.   node* first = buckets[n];   
  698.   
  699.   // 如果 buckets[n] 已被佔用,此時first 將不為0,於是進入以下迴圈,  
  700.   // 走過 bucket 所對應的整個串列。  
  701.   for (node* cur = first; cur; cur = cur->next)   
  702.     if (equals(get_key(cur->val), get_key(obj))) {  
  703.       // 如果发现链表中键值相同,马上插入,然后返回  
  704.       //插到键值相同节点的后面  
  705.       node* tmp = new_node(obj);  
  706.       tmp->next = cur->next;  
  707.       cur->next = tmp;  
  708.       ++num_elements;     
  709.       return iterator(tmp, this);   // 返回迭代器,指向新插入的节点  
  710.     }  
  711.   
  712.   // 运行到此处,没有键值重复。  
  713.   node* tmp = new_node(obj);  
  714.   tmp->next = first;  
  715.   buckets[n] = tmp;  
  716.   ++num_elements;  
  717.   return iterator(tmp, this);  
  718. }  
  719.   
  720. //如果存在obj节点则返回指向其节点的迭代器,否则插入  
  721. template <class V, class K, class HF, class Ex, class Eq, class A>  
  722. typename hashtable<V, K, HF, Ex, Eq, A>::reference   
  723. hashtable<V, K, HF, Ex, Eq, A>::find_or_insert(const value_type& obj)  
  724. {  
  725.   resize(num_elements + 1);  
  726.   
  727.   size_type n = bkt_num(obj);  
  728.   node* first = buckets[n];  
  729.   
  730.   for (node* cur = first; cur; cur = cur->next)  
  731.     if (equals(get_key(cur->val), get_key(obj)))  
  732.       return cur->val;  
  733.   
  734.   node* tmp = new_node(obj);  
  735.   tmp->next = first;  
  736.   buckets[n] = tmp;  
  737.   ++num_elements;  
  738.   return tmp->val;  
  739. }  
  740.   
  741. template <class V, class K, class HF, class Ex, class Eq, class A>  
  742. pair<typename hashtable<V, K, HF, Ex, Eq, A>::iterator,  
  743.      typename hashtable<V, K, HF, Ex, Eq, A>::iterator>   
  744. hashtable<V, K, HF, Ex, Eq, A>::equal_range(const key_type& key)  
  745. {  
  746.   typedef pair<iterator, iterator> pii;  
  747.   const size_type n = bkt_num_key(key);  
  748.   
  749.   for (node* first = buckets[n]; first; first = first->next) {  
  750.     if (equals(get_key(first->val), key)) {  
  751.       for (node* cur = first->next; cur; cur = cur->next)  
  752.         if (!equals(get_key(cur->val), key))  
  753.           return pii(iterator(first, this), iterator(cur, this));  
  754.       for (size_type m = n + 1; m < buckets.size(); ++m)  
  755.         if (buckets[m])  
  756.           return pii(iterator(first, this),  
  757.                      iterator(buckets[m], this));  
  758.       return pii(iterator(first, this), end());  
  759.     }  
  760.   }  
  761.   return pii(end(), end());  
  762. }  
  763. //查找键值等于key的区间。pair两个元素类型都是迭代器类型  
  764. //一个指向区间起始位置,一个指向区间结束的下一个位置。  
  765. template <class V, class K, class HF, class Ex, class Eq, class A>  
  766. pair<typename hashtable<V, K, HF, Ex, Eq, A>::const_iterator,   
  767.      typename hashtable<V, K, HF, Ex, Eq, A>::const_iterator>   
  768. hashtable<V, K, HF, Ex, Eq, A>::equal_range(const key_type& key) const  
  769. {  
  770.   typedef pair<const_iterator, const_iterator> pii;  
  771.   const size_type n = bkt_num_key(key);//先找到在哪个 buckets  
  772.     //bucket对应的链表中查找  
  773.   for (const node* first = buckets[n] ; first; first = first->next) {  
  774.     if (equals(get_key(first->val), key)) {//找到键值为key的起始位置  
  775.       for (const node* cur = first->next; cur; cur = cur->next)  
  776.         if (!equals(get_key(cur->val), key))  
  777.           return pii(const_iterator(first, this),  
  778.                      const_iterator(cur, this));  
  779.                        
  780.         //运行到此处,说明bucket对应的链表中尾节点也是键值为key节点  
  781.         //那么下一个位置就是 buckets中可用的bucket链表头节点  
  782.       for (size_type m = n + 1; m < buckets.size(); ++m)  
  783.         if (buckets[m])  
  784.           return pii(const_iterator(first, this),  
  785.                      const_iterator(buckets[m], this));  
  786.         //后面的 buckets都没用  
  787.       return pii(const_iterator(first, this), end());  
  788.     }  
  789.   }  
  790.   // hash table没有key值节点  
  791.   return pii(end(), end());  
  792. }  
  793. //擦除键值为key的节点  
  794. template <class V, class K, class HF, class Ex, class Eq, class A>  
  795. typename hashtable<V, K, HF, Ex, Eq, A>::size_type   
  796. hashtable<V, K, HF, Ex, Eq, A>::erase(const key_type& key)  
  797. {  
  798.   const size_type n = bkt_num_key(key);  
  799.   node* first = buckets[n];//找到对应bucket链表头节点  
  800.   size_type erased = 0;  
  801.   
  802.   if (first) {  
  803.     node* cur = first;//这里要保存前一个节点,因为是单向链表  
  804.     node* next = cur->next;  
  805.     //如果链表中多于一个节点  
  806.     while (next) {  
  807.       if (equals(get_key(next->val), key)) {  
  808.         cur->next = next->next;  
  809.         delete_node(next);  
  810.         next = cur->next;  
  811.         ++erased;  
  812.         --num_elements;  
  813.       }  
  814.       else {  
  815.         cur = next;  
  816.         next = cur->next;  
  817.       }  
  818.     }  
  819.     //链表中只有一个节点  
  820.     if (equals(get_key(first->val), key)) {  
  821.       buckets[n] = first->next;  
  822.       delete_node(first);  
  823.       ++erased;  
  824.       --num_elements;  
  825.     }  
  826.   }  
  827.   return erased;  
  828. }  
  829.   
  830. template <class V, class K, class HF, class Ex, class Eq, class A>  
  831. void hashtable<V, K, HF, Ex, Eq, A>::erase(const iterator& it)  
  832. {  
  833.   if (node* const p = it.cur) {  
  834.     const size_type n = bkt_num(p->val);  
  835.     node* cur = buckets[n];  
  836.   
  837.     if (cur == p) {  
  838.       buckets[n] = cur->next;  
  839.       delete_node(cur);  
  840.       --num_elements;  
  841.     }  
  842.     else {  
  843.       node* next = cur->next;  
  844.       while (next) {  
  845.         if (next == p) {  
  846.           cur->next = next->next;  
  847.           delete_node(next);  
  848.           --num_elements;  
  849.           break;  
  850.         }  
  851.         else {  
  852.           cur = next;  
  853.           next = cur->next;  
  854.         }  
  855.       }  
  856.     }  
  857.   }  
  858. }  
  859. //擦除两个迭代器之间的元素  
  860. template <class V, class K, class HF, class Ex, class Eq, class A>  
  861. void hashtable<V, K, HF, Ex, Eq, A>::erase(iterator first, iterator last)  
  862. {  
  863.   size_type f_bucket = first.cur ? bkt_num(first.cur->val) : buckets.size();  
  864.   size_type l_bucket = last.cur ? bkt_num(last.cur->val) : buckets.size();  
  865.   
  866.   if (first.cur == last.cur)  
  867.     return;  
  868.   else if (f_bucket == l_bucket)  
  869.     erase_bucket(f_bucket, first.cur, last.cur);  
  870.   else {  
  871.     erase_bucket(f_bucket, first.cur, 0);  
  872.     for (size_type n = f_bucket + 1; n < l_bucket; ++n)  
  873.       erase_bucket(n, 0);  
  874.     if (l_bucket != buckets.size())  
  875.       erase_bucket(l_bucket, last.cur);  
  876.   }  
  877. }  
  878.   
  879. template <class V, class K, class HF, class Ex, class Eq, class A>  
  880. inline void  
  881. hashtable<V, K, HF, Ex, Eq, A>::erase(const_iterator first,  
  882.                                       const_iterator last)  
  883. {  
  884.   erase(iterator(const_cast<node*>(first.cur),  
  885.                  const_cast<hashtable*>(first.ht)),  
  886.         iterator(const_cast<node*>(last.cur),  
  887.                  const_cast<hashtable*>(last.ht)));  
  888. }  
  889.   
  890. template <class V, class K, class HF, class Ex, class Eq, class A>  
  891. inline void  
  892. hashtable<V, K, HF, Ex, Eq, A>::erase(const const_iterator& it)  
  893. {  
  894.   erase(iterator(const_cast<node*>(it.cur),  
  895.                  const_cast<hashtable*>(it.ht)));  
  896. }  
  897. //重新配置 hash table的大小  
  898. template <class V, class K, class HF, class Ex, class Eq, class A>  
  899. void hashtable<V, K, HF, Ex, Eq, A>::resize(size_type num_elements_hint)  
  900. {  
  901.   const size_type old_n = buckets.size();//原来hash table大小  
  902.   if (num_elements_hint > old_n) {   // 确定真的需要重新配置  
  903.     const size_type n = next_size(num_elements_hint);   // 找出下一个质数  
  904.       
  905.     //下个这个判断没必要了吧?因为n>=num_elements_hint,而num_elements_hint>=old_n  
  906.     if (n > old_n) {  
  907.       vector<node*, A> tmp(n, (node*) 0); // 设立新的 buckets  
  908.       __STL_TRY {  
  909.         // 下面处理每一个旧的bucket  
  910.         for (size_type bucket = 0; bucket < old_n; ++bucket) {  
  911.           node* first = buckets[bucket]; // 指向节点所对应链表的起始节点  
  912.           // 以下處理每一個舊bucket 所含(串列)的每一個節點  
  913.           // 一下处理bucketliability的每一个节点  
  914.           while (first) {   // 链表没结束  
  915.             // 以下找出节点落在哪一个新bucket 內  
  916.             size_type new_bucket = bkt_num(first->val, n);  
  917.             // 以下四个动作颇为巧妙  
  918.             // (1) 令旧 bucket 指向其所对应之链表的下一个节点(以便迭代处理)  
  919.             buckets[bucket] = first->next;   
  920.             // (2)(3) 将当前节点安插到新的bucket内,成为其对应链表的第一个节点。  
  921.             first->next = tmp[new_bucket];     
  922.             tmp[new_bucket] = first;  
  923.             // (4) 回到旧bucket 所指的待处理链表,准备处理下一个节点  
  924.             first = buckets[bucket];            
  925.           }  
  926.         }  
  927.         buckets.swap(tmp);  // vector::swap。新旧 buckets 对调。  
  928.         // 注意,对调两方如果大小不同,大的会变小,小的会变大。  
  929.         // tmp为局部作用域,离开其作用域自动释放  
  930.       }  
  931. #         ifdef __STL_USE_EXCEPTIONS  
  932.         //commit or rollback  
  933.       catch(...) {  
  934.         for (size_type bucket = 0; bucket < tmp.size(); ++bucket) {  
  935.           while (tmp[bucket]) {  
  936.             node* next = tmp[bucket]->next;  
  937.             delete_node(tmp[bucket]);  
  938.             tmp[bucket] = next;  
  939.           }  
  940.         }  
  941.         throw;  
  942.       }  
  943. #         endif /* __STL_USE_EXCEPTIONS */  
  944.     }  
  945.   }  
  946. }  
  947. //擦除hash table对应第n个bucket中的一段元素[first last)  
  948. template <class V, class K, class HF, class Ex, class Eq, class A>  
  949. void hashtable<V, K, HF, Ex, Eq, A>::erase_bucket(const size_type n,   
  950.                                                   node* first, node* last)  
  951. {  
  952.   node* cur = buckets[n];  
  953.   if (cur == first)  
  954.     erase_bucket(n, last);  
  955.   else {  
  956.     node* next;  
  957.     for (next = cur->next; next != first; cur = next, next = cur->next)  
  958.       ;  
  959.       //下面应该是 while(next!=last)吧?否则last在这没用  
  960.     while (next) {  
  961.       cur->next = next->next;  
  962.       delete_node(next);  
  963.       next = cur->next;  
  964.       --num_elements;  
  965.     }  
  966.   }  
  967. }  
  968. 擦除hash table对应第n个bucket中的一段元素[buckets[n] last)  
  969. template <class V, class K, class HF, class Ex, class Eq, class A>  
  970. void   
  971. hashtable<V, K, HF, Ex, Eq, A>::erase_bucket(const size_type n, node* last)  
  972. {  
  973.   node* cur = buckets[n];  
  974.   while (cur != last) {  
  975.     node* next = cur->next;  
  976.     delete_node(cur);  
  977.     cur = next;  
  978.     buckets[n] = cur;  
  979.     --num_elements;  
  980.   }  
  981. }  
  982.   
  983. template <class V, class K, class HF, class Ex, class Eq, class A>  
  984. void hashtable<V, K, HF, Ex, Eq, A>::clear()  
  985. {  
  986.   // 针对每一个 bucket.  
  987.   for (size_type i = 0; i < buckets.size(); ++i) {  
  988.     node* cur = buckets[i];  
  989.     // 将 bucket list 中的每一个节点刪除掉  
  990.     while (cur != 0) {  
  991.       node* next = cur->next;  
  992.       delete_node(cur);  
  993.       cur = next;  
  994.     }  
  995.     buckets[i] = 0;     // 令bucket 內容为 null 指针  
  996.   }  
  997.   num_elements = 0;     // 令总节点个数0  
  998.   
  999.   // 注意,buckets vector 并未释放掉,仍保有原来大小。  
  1000. }  
  1001.   
  1002.       
  1003. template <class V, class K, class HF, class Ex, class Eq, class A>  
  1004. void hashtable<V, K, HF, Ex, Eq, A>::copy_from(const hashtable& ht)  
  1005. {  
  1006.   // 先清除己方的buckets vector. 调用vector::clear.   
  1007.   buckets.clear();    
  1008.   
  1009.   //如果己方空间大于对方,就不懂,否则增大己方空间等于对方  
  1010.   buckets.reserve(ht.buckets.size());   
  1011.     
  1012.   //从己方的buckets vector尾端开始,安插n个元素,其值为NULL指针。  
  1013.   //注意,此时buckets vector为空,所以所谓尾端就是起始处  
  1014.   buckets.insert(buckets.end(), ht.buckets.size(), (node*) 0);  
  1015.   __STL_TRY {  
  1016.     // 针对 buckets vector   
  1017.     for (size_type i = 0; i < ht.buckets.size(); ++i) {  
  1018.       //复制 vector 的每一个元素(是个指针,指向hash table节点)  
  1019.         
  1020.       //注意下面if语句,是先赋值再判断,它等价于  
  1021.       //const node* cur = ht.buckets[i]; if(cur)  
  1022.       if (const node* cur = ht.buckets[i]) {  
  1023.         node* copy = new_node(cur->val);  
  1024.         buckets[i] = copy;  
  1025.   
  1026.         // 针对每一个 bucket list,复制每一个节点  
  1027.         for (node* next = cur->next; next; cur = next, next = cur->next) {  
  1028.           copy->next = new_node(next->val);  
  1029.           copy = copy->next;  
  1030.         }  
  1031.       }  
  1032.     }  
  1033.     num_elements = ht.num_elements; // 重新设置节点个数(hashtable 的大小)  
  1034.   }  
  1035.   __STL_UNWIND(clear());  
  1036. }  
  1037.   
  1038. __STL_END_NAMESPACE  
  1039.   
  1040. #endif /* __SGI_STL_INTERNAL_HASHTABLE_H */  
  1041.   
  1042. // Local Variables:  
  1043. // mode:C++  
  1044. // End:  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值