stl_hashtable

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

你可能感兴趣的:(c++,stl)