📄 _hashtable.c
字号:
++__erased; } while ((__cur != __last) && _M_equals(_M_get_key(*__cur), __key)); fill(_M_buckets.begin() + __prev_b, _M_buckets.begin() + __n + 1, __cur._M_node); } else { _ElemsIte __prev = __cur++; for (; __cur != __last; ++__prev, ++__cur) { if (_M_equals(_M_get_key(*__cur), __key)) { do { __cur = _M_elems.erase_after(__prev); ++__erased; } while ((__cur != __last) && _M_equals(_M_get_key(*__cur), __key)); break; } } } _M_num_elements -= __erased; _M_reduce(); return __erased;}template <class _Val, class _Key, class _HF, class _Traits, class _ExK, class _EqK, class _All>void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All> ::erase(const_iterator __it) { const size_type __n = _M_bkt_num(*__it); _ElemsIte __cur(_M_buckets[__n]); size_type __erased = 0; if (__cur == __it._M_ite) { size_type __prev_b = __n; _ElemsIte __prev = _M_before_begin(__prev_b)._M_ite; fill(_M_buckets.begin() + __prev_b, _M_buckets.begin() + __n + 1, _M_elems.erase_after(__prev)._M_node); ++__erased; } else { _ElemsIte __prev = __cur++; _ElemsIte __last(_M_buckets[__n + 1]); for (; __cur != __last; ++__prev, ++__cur) { if (__cur == __it._M_ite) { _M_elems.erase_after(__prev); ++__erased; break; } } } _M_num_elements -= __erased; _M_reduce();}template <class _Val, class _Key, class _HF, class _Traits, class _ExK, class _EqK, class _All>void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All> ::erase(const_iterator __first, const_iterator __last) { if (__first == __last) return; size_type __f_bucket = _M_bkt_num(*__first); size_type __l_bucket = __last != end() ? _M_bkt_num(*__last) : (_M_buckets.size() - 1); _ElemsIte __cur(_M_buckets[__f_bucket]); _ElemsIte __prev; if (__cur == __first._M_ite) { __prev = _M_before_begin(__f_bucket)._M_ite; } else { _ElemsIte __last(_M_buckets[++__f_bucket]); __prev = __cur++; for (; (__cur != __last) && (__cur != __first._M_ite); ++__prev, ++__cur); } size_type __erased = 0; //We do not use the slist::erase_after method taking a range to count the //number of erased elements: while (__cur != __last._M_ite) { __cur = _M_elems.erase_after(__prev); ++__erased; } fill(_M_buckets.begin() + __f_bucket, _M_buckets.begin() + __l_bucket + 1, __cur._M_node); _M_num_elements -= __erased; _M_reduce();}template <class _Val, class _Key, class _HF, class _Traits, class _ExK, class _EqK, class _All>void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All> ::rehash(size_type __num_buckets_hint) { if (bucket_count() >= __num_buckets_hint) { // We are trying to reduce number of buckets, we have to validate it: size_type __limit_num_buckets = (size_type)((float)size() / max_load_factor()); if (__num_buckets_hint < __limit_num_buckets) { // Targetted number of buckets __num_buckets_hint would break // load_factor() <= max_load_factor() rule. return; } } _M_rehash(__num_buckets_hint);}template <class _Val, class _Key, class _HF, class _Traits, class _ExK, class _EqK, class _All>void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All> ::_M_enlarge(size_type __to_size) { size_type __num_buckets = bucket_count(); size_type __num_buckets_hint = (size_type)((float)__to_size / max_load_factor()); if (__num_buckets_hint <= __num_buckets) { return; } __num_buckets = _STLP_PRIV _Stl_prime_type::_S_next_size(__num_buckets_hint); _M_rehash(__num_buckets);}template <class _Val, class _Key, class _HF, class _Traits, class _ExK, class _EqK, class _All>void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All> ::_M_reduce() { size_type __num_buckets = bucket_count(); // We only try to reduce the hashtable if the theorical load factor // is lower than a fraction of the max load factor: // 4 factor is coming from the fact that prime number list is almost a // geometrical suite with reason 2, as we try to jump 2 levels is means // a 4 factor. if ((float)size() / (float)__num_buckets > max_load_factor() / 4.0f) return; const size_type *__first; const size_type *__prev; _STLP_PRIV _Stl_prime_type::_S_prev_sizes(__num_buckets, __first, __prev); /* We are only going to reduce number of buckets if moving to yet the previous number * of buckets in the prime numbers would respect the load rule. Otherwise algorithm * successively removing and adding an element would each time perform an expensive * rehash operation. */ const size_type *__prev_prev = __prev; if (__prev_prev != __first) { --__prev_prev; if ((float)size() / (float)*__prev_prev > max_load_factor()) return; } else { if (*__prev >= __num_buckets) return; } // Can we reduce further: while (__prev_prev != __first) { --__prev_prev; if ((float)size() / (float)*__prev_prev > max_load_factor()) // We cannot reduce further. break; --__prev; } _M_rehash(*__prev);}template <class _Val, class _Key, class _HF, class _Traits, class _ExK, class _EqK, class _All>void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All> ::_M_resize() { if (load_factor() > max_load_factor()) { // We have to enlarge _M_enlarge(size()); } else { // We can try to reduce size: _M_reduce(); }}template <class _Val, class _Key, class _HF, class _Traits, class _ExK, class _EqK, class _All>void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All> ::_M_rehash(size_type __num_buckets) {#if defined (_STLP_DEBUG) _M_check();#endif _ElemsCont __tmp_elems(_M_elems.get_allocator()); _BucketVector __tmp(__num_buckets + 1, __STATIC_CAST(_BucketType*, 0), _M_buckets.get_allocator()); _ElemsIte __cur, __last(_M_elems.end()); while (!_M_elems.empty()) { __cur = _M_elems.begin(); size_type __new_bucket = _M_bkt_num(*__cur, __num_buckets); _ElemsIte __ite(__cur), __before_ite(__cur); for (++__ite; __ite != __last && _M_equals(_M_get_key(*__cur), _M_get_key(*__ite)); ++__ite, ++__before_ite); size_type __prev_bucket = __new_bucket; _ElemsIte __prev = _S_before_begin(__tmp_elems, __tmp, __prev_bucket)._M_ite; __tmp_elems.splice_after(__prev, _M_elems, _M_elems.before_begin(), __before_ite); fill(__tmp.begin() + __prev_bucket, __tmp.begin() + __new_bucket + 1, __cur._M_node); } _M_elems.swap(__tmp_elems); _M_buckets.swap(__tmp);}#if defined (_STLP_DEBUG)template <class _Val, class _Key, class _HF, class _Traits, class _ExK, class _EqK, class _All>void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>::_M_check() const { //We check that hash code of stored keys haven't change and also that equivalent //relation hasn't been modified size_t __num_buckets = bucket_count(); for (size_t __b = 0; __b < __num_buckets; ++__b) { _ElemsIte __cur(_M_buckets[__b]), __last(_M_buckets[__b + 1]); _ElemsIte __fst(__cur), __snd(__cur); for (; __cur != __last; ++__cur) { _STLP_ASSERT( _M_bkt_num(*__cur, __num_buckets) == __b ) _STLP_ASSERT( !_M_equals(_M_get_key(*__fst), _M_get_key(*__cur)) || _M_equals(_M_get_key(*__snd), _M_get_key(*__cur)) ) if (__fst != __snd) ++__fst; if (__snd != __cur) ++__snd; } }}#endiftemplate <class _Val, class _Key, class _HF, class _Traits, class _ExK, class _EqK, class _All>void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>::clear() { _M_elems.clear(); _M_buckets.assign(_M_buckets.size(), __STATIC_CAST(_BucketType*, 0)); _M_num_elements = 0;}template <class _Val, class _Key, class _HF, class _Traits, class _ExK, class _EqK, class _All>void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All> ::_M_copy_from(const hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>& __ht) { _M_elems.clear(); _M_elems.insert(_M_elems.end(), __ht._M_elems.begin(), __ht._M_elems.end()); _M_buckets.resize(__ht._M_buckets.size()); _ElemsConstIte __src(__ht._M_elems.begin()), __src_end(__ht._M_elems.end()); _ElemsIte __dst(_M_elems.begin()); typename _BucketVector::const_iterator __src_b(__ht._M_buckets.begin()), __src_end_b(__ht._M_buckets.end()); typename _BucketVector::iterator __dst_b(_M_buckets.begin()), __dst_end_b(_M_buckets.end()); for (; __src != __src_end; ++__src, ++__dst) { for (; __src_b != __src_end_b; ++__src_b, ++__dst_b) { if (*__src_b == __src._M_node) { *__dst_b = __dst._M_node; } else break; } } fill(__dst_b, __dst_end_b, __STATIC_CAST(_BucketType*, 0)); _M_num_elements = __ht._M_num_elements; _M_max_load_factor = __ht._M_max_load_factor;}#undef __iterator__#undef const_iterator#undef __size_type__#undef __reference__#undef size_type#undef value_type#undef key_type#undef __stl_num_primes#if defined (_STLP_DEBUG)# undef hashtable_STLP_MOVE_TO_STD_NAMESPACE#endif_STLP_END_NAMESPACE#endif /* _STLP_HASHTABLE_C */// Local Variables:// mode:C++// End:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -