STL關聯容器

這裏簡單學習一下STL關聯容器,主要是map、multimap、set、multiset以及unordered_map。前四個底層實現都是利用紅黑樹實現的,查找算法時間複雜度爲O(log(n)),而unordered_map從名字上就知道是無序容器,其實現原理類似哈希表,查找算法時間複雜度O(1)

set、multiset、map、multimap

set容器是一個存儲有序唯一元素的數據結構。不允許有重複元素。其底層實現爲紅黑樹。multiset原理與set相同,不同的是允許有重複元素存在。

map映射是可以用任何類型的數據作爲索引的表,不允許有重複元素,其實現原理與set類似,底層都是紅黑樹。multimap允許有重複元素存在。

template<typename _Key, typename _Compare = std::less<_Key>,typename _Alloc = std::allocator<_Key> >
class set 
public:
    typedef _Key     key_type;
    typedef _Key     value_type;    // 與map不同
    typedef _Compare key_compare;
    typedef _Compare value_compare; 
    typedef _Alloc   allocator_type;

private:
    typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template rebind<_Key>::other _Key_alloc_type;
    typedef _Rb_tree<key_type, value_type, _Identity<value_type>, key_compare, _Key_alloc_type> _Rep_type;
    
    _Rep_type _M_t;  // Red-black tree representing set.    紅黑樹

    typedef __gnu_cxx::__alloc_traits<_Key_alloc_type> _Alloc_traits;

#if __cplusplus > 201402L
      using node_type = typename _Rep_type::node_type;
      using insert_return_type = typename _Rep_type::insert_return_type;
#endif

map與set其實現原理類似,不同的是map中每個元素是std::pair對。

template <typename _Key, typename _Tp, typename _Compare = std::less<_Key>,typename _Alloc=std::allocator<std::pair<const _Key, _Tp> > >
class map {
public:
    typedef _Key key_type;
    typedef _Tp mapped_type;
    typedef std::pair<const _Key, _Tp> value_type;      // 其值是pair對的形式存儲
    typedef _Compare key_compare;                       // RB-tree,需要對元素進行比較
    typedef _Alloc allocator_type;

private:
    /// This turns a red-black tree into a [multi]map.
    typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template rebind<value_type>::other _Pair_alloc_type;
    typedef _Rb_tree<key_type, value_type, _Select1st<value_type>, key_compare, _Pair_alloc_type> _Rep_type;

    /// The actual tree structure.
    _Rep_type _M_t;     // 底層實現RB-tree

    typedef __gnu_cxx::__alloc_traits<_Pair_alloc_type> _Alloc_traits;

public:
    // 重載[]
    mapped_type& operator[](const key_type& __k) {
	    // concept requirements
	    __glibcxx_function_requires(_DefaultConstructibleConcept<mapped_type>)
        iterator __i = lower_bound(__k);
	    // __i->first is greater than or equivalent to __k.
	    if (__i == end() || key_comp()(__k, (*__i).first))
#if __cplusplus >= 201103L
	        __i = _M_t._M_emplace_hint_unique(__i, std::piecewise_construct, std::tuple<const key_type&>(__k),
std::tuple<>());
#else
	        __i = insert(__i, value_type(__k, mapped_type()));
#endif
	    return (*__i).second;
    }
}

其他具體實現細節這裏不再列出,只要懂紅黑樹的原理,很容易理解。

unordered_map

這個實現與map不同,其底層是哈希表,理解了哈希表就很容易理解unordered_map。

template<class _Key, class _Tp,class _Hash = hash<_Key>,class _Pred = std::equal_to<_Key>,class _Alloc=std::allocator<std::pair<const _Key, _Tp> > >
class unordered_map {
    typedef __umap_hashtable<_Key, _Tp, _Hash, _Pred, _Alloc>  _Hashtable;
    _Hashtable _M_h;    // 可以看到底層實現是哈希表

public:
    // typedefs:
    //@{
    /// Public typedefs.
    typedef typename _Hashtable::key_type	key_type;
    typedef typename _Hashtable::value_type	value_type;
    typedef typename _Hashtable::mapped_type	mapped_type;
    typedef typename _Hashtable::hasher	hasher;
    typedef typename _Hashtable::key_equal	key_equal;
    typedef typename _Hashtable::allocator_type allocator_type;
    //@}

#if __cplusplus > 201402L
      using node_type = typename _Hashtable::node_type;
      using insert_return_type = typename _Hashtable::insert_return_type;
#endif
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章