2013-03-31 83 views
1

SGI STL使用單獨的鏈接來實現哈希表。它包含一個桶向量,每個元素是桶列表的第一個節點鏈接。有時候,如果插入哈希表的元素太多,我們必須調整矢量的大小。但是,我們應該什麼時候調整矢量大小?SGI STL可以這樣做:比較新元素的數量與舊矢量的大小。如果前者較大,則調整矢量大小。 vector的元素只是存儲桶列表的第一個節點鏈接!但是存儲桶linklist可以包含很多元素,爲什麼它沒有考慮這個問題?STL哈希表調整大小

以下是SGI STL源代碼(來自enter link description here):

template <class _Val, class _Key, class _HashFcn, 
      class _ExtractKey, class _EqualKey, class _Alloc> 
class hashtable { 
public: 
    typedef _Key key_type; 
    typedef _Val value_type; 
    typedef _HashFcn hasher; 
    typedef _EqualKey key_equal; 

    typedef size_t   size_type; 
    typedef ptrdiff_t   difference_type; 
    typedef value_type*  pointer; 
    typedef const value_type* const_pointer; 
    typedef value_type&  reference; 
    typedef const value_type& const_reference; 

    hasher hash_funct() const { return _M_hash; } 
    key_equal key_eq() const { return _M_equals; } 

private: 
    typedef _Hashtable_node<_Val> _Node; 

#ifdef __STL_USE_STD_ALLOCATORS 
public: 
    typedef typename _Alloc_traits<_Val,_Alloc>::allocator_type allocator_type; 
    allocator_type get_allocator() const { return _M_node_allocator; } 
private: 
    typename _Alloc_traits<_Node, _Alloc>::allocator_type _M_node_allocator; 
    _Node* _M_get_node() { return _M_node_allocator.allocate(1); } 
    void _M_put_node(_Node* __p) { _M_node_allocator.deallocate(__p, 1); } 
# define __HASH_ALLOC_INIT(__a) _M_node_allocator(__a), 
#else /* __STL_USE_STD_ALLOCATORS */ 
public: 
    typedef _Alloc allocator_type; 
    allocator_type get_allocator() const { return allocator_type(); } 
private: 
    typedef simple_alloc<_Node, _Alloc> _M_node_allocator_type; 
    _Node* _M_get_node() { return _M_node_allocator_type::allocate(1); } 
    void _M_put_node(_Node* __p) { _M_node_allocator_type::deallocate(__p, 1); } 
# define __HASH_ALLOC_INIT(__a) 
#endif /* __STL_USE_STD_ALLOCATORS */ 

private: 
    hasher    _M_hash; 
    key_equal    _M_equals; 
    _ExtractKey   _M_get_key; 
    vector<_Node*,_Alloc> _M_buckets;//Here!!!!! 
    size_type    _M_num_elements; 

請參閱私人元件_M_buckets

和矢量調整代碼SGI STL的:

template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> 
void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All> 
    ::resize(size_type __num_elements_hint) 
{ 
    const size_type __old_n = _M_buckets.size(); 
    if (__num_elements_hint > __old_n) { 
    const size_type __n = _M_next_size(__num_elements_hint); 
    if (__n > __old_n) { 
     vector<_Node*, _All> __tmp(__n, (_Node*)(0), 
           _M_buckets.get_allocator()); 
     __STL_TRY { 
     for (size_type __bucket = 0; __bucket < __old_n; ++__bucket) { 
      _Node* __first = _M_buckets[__bucket];//Here!! 
      while (__first) { 
      size_type __new_bucket = _M_bkt_num(__first->_M_val, __n); 
      _M_buckets[__bucket] = __first->_M_next; 
      __first->_M_next = __tmp[__new_bucket]; 
      __tmp[__new_bucket] = __first; 
      __first = _M_buckets[__bucket];   
      } 
     } 
     _M_buckets.swap(__tmp); 
     } 

和易於鬥載體:

template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> 
void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All> 
    ::_M_erase_bucket(const size_type __n, _Node* __first, _Node* __last) 
{ 
    _Node* __cur = _M_buckets[__n]; 
    if (__cur == __first) 
    _M_erase_bucket(__n, __last); 
    else { 
    _Node* __next; 
    for (__next = __cur->_M_next; 
     __next != __first; 
     __cur = __next, __next = __cur->_M_next) 
     ; 
    while (__next != __last) { 
     __cur->_M_next = __next->_M_next; 
     _M_delete_node(__next); 
     __next = __cur->_M_next; 
     --_M_num_elements; 
    } 
    } 
} 

我們可以看到,向量的元素是第一存儲桶鏈表的節點鏈接!

我的問題是,爲什麼SGI STL這樣做?Thx!

+1

由於現有矢量不足以容納所有新元素,因此需要重新定位以容納新元素。 –

+0

@AlokSave vector的元素只是bucket列表中的第一個節點鏈接!!!!但linklist可以包含很多元素,爲什麼它沒有想到這個? – XiaJun

+0

無論如何,你指的是哪一類? hash_map,hash_set,unordered_map,unordered_set,hash_table?哪個版本?請(a)顯示代碼或(b)鏈接到相關文檔頁 – sehe

回答

0

std::vector如果插入元素的數量超過其容量,將自動重新分配。整體而言,這不僅僅是在這種情況下,對於std::vector也是如此。

+0

vector的元素只是bucket列表中的第一個節點鏈接!!!!但linklist可以包含很多元素,爲什麼它沒有想到這個? – XiaJun

1

vector的元素只是bucket列表的第一個節點鏈接!

向量的元素顯然不是「只有桶列表的第一個節點鏈接」。

相反,存在一個存儲區而不是存儲區列表。

如果您需要存儲桶列表,請使用std::list作爲存儲桶。

+0

我已經發布了來自SGI STL的源代碼,謝謝! – XiaJun

+0

無需重新發布您的所有評論:)此外,更少的感嘆號會遇到很多友善的。歡迎來到SO – sehe