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: