1 // Filename: stl_hashtable.h 2 3 // Comment By: 凝霜 4 // E-mail: mdl2009@vip.qq.com 5 // Blog: http://blog.youkuaiyun.com/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 <stl_algobase.h> 60 #include <stl_alloc.h> 61 #include <stl_construct.h> 62 #include <stl_tempbuf.h> 63 #include <stl_algo.h> 64 #include <stl_uninitialized.h> 65 #include <stl_function.h> 66 #include <stl_vector.h> 67 #include <stl_hash_fun.h> 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<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc> 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<Value> 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 // 如果编译器支持'->'则重载, 详细见我在<stl_list.h>中的剖析 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<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc> 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<Value> 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 // 详细剖析参考<stl_fun_fun.h> 227 hasher hash; 228 key_equal equals; 229 ExtractKey get_key; 230 231 typedef __hashtable_node<Value> node; 232 typedef simple_alloc<node, Alloc> node_allocator; 233 234 vector<node*,Alloc> 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<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>; 248 friend struct 249 __hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>; 250 251 public: 252 // 下面这些函数STL容器的表现基本一致, 253 // 不做说明, 可以参看<stl_vector.h>, <stl_list.h>中的解析 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 pair<iterator, bool> 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 pair<iterator, bool> 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<iterator, iterator> equal_range(const key_type& key); 487 pair<const_iterator, const_iterator> 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<V, K, HF, ExK, EqK, A>& 562 __hashtable_iterator<V, K, HF, ExK, EqK, A>::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<V, K, HF, ExK, EqK, A> 581 __hashtable_iterator<V, K, HF, ExK, EqK, A>::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<V, K, HF, ExK, EqK, A>& 591 __hashtable_const_iterator<V, K, HF, ExK, EqK, A>::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<V, K, HF, ExK, EqK, A> 605 __hashtable_const_iterator<V, K, HF, ExK, EqK, A>::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<V, K, HF, ExK, EqK, All>&) 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<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_iterator<V, K, HF, ExK, EqK, All>&) 631 { 632 return (hashtable<V, K, HF, ExK, EqK, All>::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<V, K, HF, ExK, EqK, All>&) 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<V, K, HF, ExK, EqK, All>&) 645 { 646 return (V*) 0; 647 } 648 649 template <class V, class K, class HF, class ExK, class EqK, class All> 650 inline hashtable<V, K, HF, ExK, EqK, All>::difference_type* 651 distance_type(const __hashtable_const_iterator<V, K, HF, ExK, EqK, All>&) 652 { 653 return (hashtable<V, K, HF, ExK, EqK, All>::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<V, K, HF, Ex, Eq, A>& ht1, 660 const hashtable<V, K, HF, Ex, Eq, A>& ht2) 661 { 662 typedef typename hashtable<V, K, HF, Ex, Eq, A>::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<Val, Key, HF, Extract, EqKey, A>& ht1, 683 hashtable<Val, Key, HF, Extract, EqKey, A>& 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<typename hashtable<V, K, HF, Ex, Eq, A>::iterator, bool> 693 hashtable<V, K, HF, Ex, Eq, A>::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 pair<iterator, bool>(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 pair<iterator, bool>(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<V, K, HF, Ex, Eq, A>::iterator 716 hashtable<V, K, HF, Ex, Eq, A>::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<V, K, HF, Ex, Eq, A>::reference 740 hashtable<V, K, HF, Ex, Eq, A>::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<typename hashtable<V, K, HF, Ex, Eq, A>::iterator, 761 typename hashtabfind_or_insertle<V, K, HF, Ex, Eq, A>::iterator> 762 hashtable<V, K, HF, Ex, Eq, A>::equal_range(const key_type& key) 763 { 764 typedef pair<iterator, iterator> 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<typename hashtable<V, K, HF, Ex, Eq, A>::const_iterator, 784 typename hashtable<V, K, HF, Ex, Eq, A>::const_iterator> 785 hashtable<V, K, HF, Ex, Eq, A>::equal_range(const key_type& key) const 786 { 787 typedef pair<const_iterator, const_iterator> 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<V, K, HF, Ex, Eq, A>::size_type 809 hashtable<V, K, HF, Ex, Eq, A>::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<V, K, HF, Ex, Eq, A>::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<V, K, HF, Ex, Eq, A>::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<V, K, HF, Ex, Eq, A>::erase(const_iterator first, 896 const_iterator last) 897 { 898 erase(iterator(const_cast<node*>(first.cur), 899 const_cast<hashtable*>(first.ht)), 900 iterator(const_cast<node*>(last.cur), 901 const_cast<hashtable*>(last.ht))); 902 } 903 904 template <class V, class K, class HF, class Ex, class Eq, class A> 905 inline void 906 hashtable<V, K, HF, Ex, Eq, A>::erase(const const_iterator& it) 907 { 908 erase(iterator(const_cast<node*>(it.cur), 909 const_cast<hashtable*>(it.ht))); 910 } 911 912 // 调整hashtable的容量 913 template <class V, class K, class HF, class Ex, class Eq, class A> 914 void hashtable<V, K, HF, Ex, Eq, A>::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<node*, A> 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<V, K, HF, Ex, Eq, A>::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<V, K, HF, Ex, Eq, A>::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<V, K, HF, Ex, Eq, A>::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<V, K, HF, Ex, Eq, A>::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:
stl_hashtable
最新推荐文章于 2024-05-12 13:46:11 发布