STL之关联容器


一、关联容器概述

关联容器支持高效的关键字查找和访问。两个主要的关联容器类型是 map 和 set。map中的元素是一些关键字-值(key-value)对:关键字起到索引的作用,值则表示与索引相关联的数据。set 中每个元素只包含一个关键字。

标准库提供8个关联容器,这8个关联容器间的不同体现在三个维度上:每个容器(1)或者是一个 set,或者是一个 map;(2)或者要求不重复的关键字,或者允许重复的关键字;(3)按顺序保存元素,或无序保存。允许重复关键字的容器的名字中都包含单词 multi;不保持关键字按顺序存储的容器的名字都以单词 unordered 开头。

在这里插入图片描述

有序关联容器基于一个序标准(默认是小于比较操作<)进行查找。这类容器用平衡二叉树实现,通常是红黑树(有关红黑树的内容请参看 STL之红黑树)。

无序关联容器基于一个哈希函数进行查找。这类容器用哈希表实现,采用溢出链表策略(有关哈希表的内容请参看STL之哈希表)。

二、关联容器

2.1、set

set 的特性是,所有元素都会根据元素的键值自动被排序。由于 set 元素值就是其键值,关系到 set 元素的排列规则,因此不可以通过 set 的迭代器改变 set 的值。

标准库的 set 以 RB-tree 为底层机制,set 操作通过调用 RB-tree 的接口实现:

template <typename _Key, typename _Compare = std::less<_Key>,
          typename _Alloc = std::allocator<_Key>>
class set
{
  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.

  std::pair<iterator, bool>
  insert(value_type &&__x)
  {
    std::pair<typename _Rep_type::iterator, bool> __p =
        _M_t._M_insert_unique(std::move(__x));
    return std::pair<iterator, bool>(__p.first, __p.second);
  }
  ...
};

2.2、multiset

multiset 的特性以及用法和 set 完全相同,唯一的差别在于它允许键值重复,因此它的插入操作采用的是底层机制 RB-tree 的 _M_insert_equal() 而非 _M_insert_unique()。

template <typename _Key, typename _Compare = std::less<_Key>,
          typename _Alloc = std::allocator<_Key>>
class multiset
{
  /// This turns a red-black tree into a [multi]set.
  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;
  /// The actual tree structure.
  _Rep_type _M_t;

  iterator
  insert(value_type &&__x)
  {
    return _M_t._M_insert_equal(std::move(__x));
  }
  ...
};

2.3、map

map 的特性是,所有元素都会根据元素的键值自动被排序。map 的所有元素都是 pair,同时拥有实值和键值。

标准库的 map 以 RB-tree 为底层机制,map 操作通过调用 RB-tree 的接口实现:

template <typename _Key, typename _Tp, typename _Compare = std::less<_Key>,
          typename _Alloc = std::allocator<std::pair<const _Key, _Tp>>>
class map
{
  /// 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;

  std::pair<iterator, bool>
  insert(value_type &&__x)
  {
    return _M_t._M_insert_unique(std::move(__x));
  }
  ...
};

2.4、multimap

multimap的特性以及用法和 map 完全相同,唯一的差别在于它允许键值重复,因此它的插入操作采用的是底层机制 RB-tree 的 _M_insert_equal() 而非 _M_insert_unique()。

template <typename _Key, typename _Tp,
          typename _Compare = std::less<_Key>,
          typename _Alloc = std::allocator<std::pair<const _Key, _Tp>>>
class multimap
{
  /// 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;

  iterator
  insert(value_type &&__x)
  {
    return _M_t._M_insert_equal(std::move(__x));
  }
  ...
};

2.5、unordered_set

unordered_set以哈希表为底层机制,unordered_set操作通过调用哈希表的接口实现:

/// Base types for unordered_set.
template <bool _Cache>
using __uset_traits = __detail::_Hashtable_traits<_Cache, true, true>;

template <typename _Value,
          typename _Hash = hash<_Value>,
          typename _Pred = std::equal_to<_Value>,
          typename _Alloc = std::allocator<_Value>,
          typename _Tr = __uset_traits<__cache_default<_Value, _Hash>::value>>
using __uset_hashtable = _Hashtable<_Value, _Value, _Alloc,
                                    __detail::_Identity, _Pred, _Hash,
                                    __detail::_Mod_range_hashing,
                                    __detail::_Default_ranged_hash,
                                    __detail::_Prime_rehash_policy, _Tr>;

template <typename _Value,
          typename _Hash = hash<_Value>,
          typename _Pred = equal_to<_Value>,
          typename _Alloc = allocator<_Value>>
class unordered_set
{
  typedef __uset_hashtable<_Value, _Hash, _Pred, _Alloc> _Hashtable;
  _Hashtable _M_h;

  std::pair<iterator, bool>
  insert(value_type &&__x)
  {
    return _M_h.insert(std::move(__x));
  }
  ...
};

2.6、unordered_multiset

unordered_multiset的特性以及用法和 unordered_set完全相同,唯一的差别在于它允许键值重复。

/// Base types for unordered_multiset.
template <bool _Cache>
using __umset_traits = __detail::_Hashtable_traits<_Cache, true, false>;

template <typename _Value,
          typename _Hash = hash<_Value>,
          typename _Pred = std::equal_to<_Value>,
          typename _Alloc = std::allocator<_Value>,
          typename _Tr = __umset_traits<__cache_default<_Value, _Hash>::value>>
using __umset_hashtable = _Hashtable<_Value, _Value, _Alloc,
                                     __detail::_Identity,
                                     _Pred, _Hash,
                                     __detail::_Mod_range_hashing,
                                     __detail::_Default_ranged_hash,
                                     __detail::_Prime_rehash_policy, _Tr>;

template <typename _Value,
          typename _Hash = hash<_Value>,
          typename _Pred = equal_to<_Value>,
          typename _Alloc = allocator<_Value>>
class unordered_multiset
{
  typedef __umset_hashtable<_Value, _Hash, _Pred, _Alloc> _Hashtable;
  _Hashtable _M_h;

  iterator
  insert(value_type &&__x)
  {
    return _M_h.insert(std::move(__x));
  }
  ...
};

2.7、unordered_map

unordered_map以哈希表为底层机制,unordered_map操作通过调用哈希表的接口实现:

/// Base types for unordered_map.
template <bool _Cache>
using __umap_traits = __detail::_Hashtable_traits<_Cache, false, true>;

template <typename _Key,
          typename _Tp,
          typename _Hash = hash<_Key>,
          typename _Pred = std::equal_to<_Key>,
          typename _Alloc = std::allocator<std::pair<const _Key, _Tp>>,
          typename _Tr = __umap_traits<__cache_default<_Key, _Hash>::value>>
using __umap_hashtable = _Hashtable<_Key, std::pair<const _Key, _Tp>,
                                    _Alloc, __detail::_Select1st,
                                    _Pred, _Hash,
                                    __detail::_Mod_range_hashing,
                                    __detail::_Default_ranged_hash,
                                    __detail::_Prime_rehash_policy, _Tr>;

template <typename _Key, typename _Tp,
          typename _Hash = hash<_Key>,
          typename _Pred = equal_to<_Key>,
          typename _Alloc = allocator<std::pair<const _Key, _Tp>>>
class unordered_map
{
  typedef __umap_hashtable<_Key, _Tp, _Hash, _Pred, _Alloc> _Hashtable;
  _Hashtable _M_h;

  template <typename _Pair>
  __enable_if_t<is_constructible<value_type, _Pair &&>::value,
                pair<iterator, bool>>
  insert(_Pair &&__x)
  {
    return _M_h.emplace(std::forward<_Pair>(__x));
  }
  ...
};

2.8、unordered_multimap

unordered_multimap的特性以及用法和 unordered_map完全相同,唯一的差别在于它允许键值重复。

/// Base types for unordered_multimap.
template <bool _Cache>
using __ummap_traits = __detail::_Hashtable_traits<_Cache, false, false>;

template <typename _Key,
          typename _Tp,
          typename _Hash = hash<_Key>,
          typename _Pred = std::equal_to<_Key>,
          typename _Alloc = std::allocator<std::pair<const _Key, _Tp>>,
          typename _Tr = __ummap_traits<__cache_default<_Key, _Hash>::value>>
using __ummap_hashtable = _Hashtable<_Key, std::pair<const _Key, _Tp>,
                                     _Alloc, __detail::_Select1st,
                                     _Pred, _Hash,
                                     __detail::_Mod_range_hashing,
                                     __detail::_Default_ranged_hash,
                                     __detail::_Prime_rehash_policy, _Tr>;

template <typename _Key, typename _Tp,
          typename _Hash = hash<_Key>,
          typename _Pred = equal_to<_Key>,
          typename _Alloc = allocator<std::pair<const _Key, _Tp>>>
class unordered_multimap
{
  typedef __ummap_hashtable<_Key, _Tp, _Hash, _Pred, _Alloc> _Hashtable;
  _Hashtable _M_h;

  template <typename _Pair>
  __enable_if_t<is_constructible<value_type, _Pair &&>::value, iterator>
  insert(_Pair &&__x)
  {
    return _M_h.emplace(std::forward<_Pair>(__x));
  }
  ...
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值