Map&&Set

STL- Map&&Set

RB_Tree

​ 非公开,这是map,set的底层支撑。它在STL中的实现:

 struct _Rb_tree_node_base
  {
    typedef _Rb_tree_node_base* _Base_ptr;//指向树节点的指针
    typedef const _Rb_tree_node_base* _Const_Base_ptr;//同上但是是const型

    _Rb_tree_color  _M_color;//枚举类型,如下
    _Base_ptr       _M_parent;
    _Base_ptr       _M_left;
    _Base_ptr       _M_right;
  }
  enum _Rb_tree_color { _S_red = false, _S_black = true };//以上均可在mingw7.2.0中找到。
  //由于新版的_RB_tree有许多继承关系,这里直接贴出《STL源码解析》的RB_tree
template<class Key,
         class Value,
         class KeyOfValue,
         class Compare,
         class Alloc = alloc>
class rb_tree{//mingw7.2.0中为_Rb_tree
protected:
    typedef _rb_tree_node<Value> rb_tree_node;
public:
    typedef rb_tree_node* link_type;
protected:
    //红黑树以三个数据表现它
    size_type node_count;//节点数量
    link_type header;
    Compare key_compare;//key比较关系,是一个仿函数
}

有下图表示这个结构:

在这里插入图片描述
​ head并非是根节点,而是拥有指向最左端和最右端的指针的一个额外节点。而无论是map以及set他们的begin()以及end()都是以上图进行返回的。而迭代器的访问顺序正是在指定比较关系下的逻辑关系。

map&&set

​ 标准模板库中,除了sequence containers(序列式容器),也有associative containers(关联式容器)。其中关联式容器包含setmapmultisetmultimap。这些容器的底层实现是红黑树,map以及set均有红黑树作为数据成员来实现各种功能。

​ map的模板参数;

template < class Key,                                     // map::key_type
           class T,                                       // map::mapped_type
           class Compare = less<Key>,                     // map::key_compare
           class Alloc = allocator<pair<const Key,T> >    // map::allocator_type
           > class map;

​ map的值类型实际上是

typedef pair<const Key, T> value_type;

​ pair的定义如下:

template<typename _T1, typename _T2>
struct pair
{
    typedef _T1 first_type;    /// @c first_type is the first bound type
    typedef _T2 second_type;   /// @c second_type is the second bound type
    _T1 first;                 /// @c first is a copy of the first object
    _T2 second;                /// @c second is a copy of the second object
    //除此之外定义了各种重载,此处略
}

​ set的模板参数:

template < class T,                        // set::key_type/value_type
           class Compare = less<T>,        // set::key_compare/value_compare
           class Alloc = allocator<T>      // set::allocator_type
           > class set;

​ set并无映射值,只有key值。并且需要指定Compare类型(仿函数,key之间的比较关系),其中less是标准模板库中的仿函数:

 template<typename _Tp>
 struct less : public binary_function<_Tp, _Tp, bool>
 {
     bool
     operator()(const _Tp& __x, const _Tp& __y) const
     { return __x < __y; }
 };

map/set的具体使用如下:

构造、析构、赋值

构造

没有fill类型的构造函数(对于map,set,key是唯一的)

map:

构造函数类型 函数原型(C++14)
empty(1) map();
explicit map (const key_compare& comp, const allocator_type&alloc=allocator_type());
explicit map (const allocator_type& alloc);
range (2) template< class InputIterator>
map(InputIterator first,InputIterator last,constkey_compare &comp = key_compare() ,const allocator_type& = allocator_type());
template< class InputIterator>
map (InputIterator first, InputIterator last,const allocator_type& = allocator_type());
copy (3) map (const map& x);
map (const map& x, const allocator_type& alloc);
move (4) map (map&& x);
map (map&& x, const allocator_type& alloc);
initializerlist(5) map (initializer_list il, const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type());
map (initializer_list il, const allocator_type& alloc = allocator_type());

set:

构造函数类型 函数原型(C++14)
empty(1) set();
explicit set (const key_compare& comp, const allocator_type& alloc = allocator_type());
explicit set (const allocator_type& alloc);
range (2) template< class InputIterator>
set (InputIterator first, InputIterator last, const key_compare& comp = key_compare(), const allocator_type& = allocator_type());
template< class InputIterator>
set (InputIterator first, InputIterator last,const allocator_type& = allocator_type());
copy (3) set (const set& x);
set (const set& x, const allocator_type& alloc)
move (4) set (set&& x);
set (set&& x, const allocator_type& alloc);
initializerlist(5) set (initializer_list il, const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type());
set (initializer_list il, const allocator_type& alloc = allocator_type());

析构

map:~map();

set:~set();

赋值

map:

operator =

函数类型 函数原型
copy (1) map& operator= (const map& x);
move (2) map& operator= (map&& x)
initializer list (3) map& operator= (initializer_list il);

没有assign

set:

函数类型 函数原型
copy (1) set& operator= (const set& x);
move (2) set& operator= (set&& x);
initializer list (3) set& operator= (initializer_list<value_type> il);

同样也没有assign

迭代器

​ map与set迭代函数一致:

函数类型 函数功能及其原型
begin
cbegin
returns an iterator to the beginning (public member function)
iterator begin();
const_iterator begin() const;
const_iterator cbegin() const;
end
cend
returns an iterator to the end (public member function)
iterator end();
const_iterator end() const;
const_iterator cend() const;
rbegin
crbegin
returns a reverse iterator to the beginning (public member function)
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
const_reverse_iterator crbegin() const;
rend
crend
returns a reverse iterator to the end (public member function)
reverse_iterator rend();
const_reverse_iterator rend() const;
const_reverse_iterator crend() const;

​ 迭代器类型为Bidirectional Iterator:双向迭代器。其中map迭代器指向的是*typedef pair<const Key, T> value_type;*这种类型。而set指向的就是key_type。既然迭代器类型为双向迭代器。那么迭代器++,迭代器–,会分别去走向哪呢?是根据比较关系来确定++、–后的元素嘛?迭代器的顺序是key_type在compare仿函数定义的比较关系下的逻辑顺序。默认的less仿函数,就是递增的访问元素。因此递增访问迭代器,能得到按照key从小到大的排序。

​ 同样值得说明的是,begin()以及 end()它们到底指向哪一个元素,由之前的红黑树的实现图可清楚知道。

​ 另外,当尝试通过迭代器修改key值时(无论是map或set),编译器报错表达式必须是可修改的左值。实际上为了维护红黑树的正常结构。map与set的迭代器都做了处理使得不能通过迭代器去修改key值。但是对于map的Value值是可以通过迭代器修改的。

大小与修改

大小有关函数

函数 函数说明及其原型
empty checks whether the container is empty (public member function)
bool empty() const;
size returns the number of elements (public member function)
size_type size() const;
max_size returns the maximum possible number of elements (public member function)
size_type max_size() const;

修改内容

map:

Modifiers
clear clears the contents (public member function)
void clear();
insert inserts elements or nodes (public member function),对于insert,它插入单个元素时,返回的是,pair<iterator,bool> ,插入成功bool为true,iterator返回插入元素的迭代器,反之bool为false,iterator为已有key的元素。
single element (1)
—pair<iterator,bool> insert (const value_type& val);
—template < class P>
—pair<iterator,bool> insert (P&& val);
with hint (2)
—iterator insert (const_iterator position, const value_type& val);
—template < class P>
— iterator insert (const_iterator position, P&& val);
range (3)
—template < class InputIterator>
— void insert (InputIterator first, InputIterator last);
initializer list (4)
—void insert (initializer_list<value_type> il);
insert_or_assign(C++17))
(map有而set无)
inserts an element or assigns to the current element if the key already exists (public member function),可以理解为覆盖版本的insert,之前insert如果有相同的key不会覆盖之前的value值,这个会
(1) (since C++17)
template < class M>
pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
(2) (since C++17)
template < class M>
pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
(3) (since C++17)
template < class M>
iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
(4) (since C++17)
template < class M>
iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
emplace(C++11) constructs element in-place (public member function)如果已经存在key,则返回该key对应的元素迭代器,以及false。否则根据参数构造一个元素,并融入map中,返回其迭代器以及true。
template <class… Args>
pair<iterator,bool> emplace (Args&&… args);
emplace_hint (C++11) constructs elements in-place using a hint (public member function)
template <class… Args>
iterator emplace_hint (const_iterator position, Args&&… args);
try_emplace (C++17)
(map有而set无)
inserts in-place if the key does not exist, does nothing if the key exists (public member function)
(1) (since C++17)
template <class… Args>
pair<iterator, bool> try_emplace(const key_type& k, Args&&… args);
(2) (since C++17)
template <class… Args>
pair<iterator, bool> try_emplace(key_type&& k, Args&&… args);
(3) (since C++17)
template <class… Args>
iterator try_emplace(const_iterator hint, const key_type& k, Args&&… args);
(4) (since C++17)
template <class… Args>
iterator try_emplace(const_iterator hint, key_type&& k, Args&&… args);
erase erases elements (public member function),返回的迭代器均为删除元素的下一个元素,若是最后一个元素,则返回的是end()
(1) iterator erase (const_iterator position);
(2) size_type erase (const key_type& k);//返回的是删除元素的个数
(3) iterator erase (const_iterator first, const_iterator last);
swap swaps the contents (public member function)
void swap (map& x);
extract (C++17) extracts nodes from the container (public member function),相比于erase不会清除元素所占空间,但是会断开在map中的连接。注意返回的是一个特殊的类型,可以在最新参考文档中查询。
(1) (since C++17)
node_type extract( const_iterator position );
(2) (since C++17)
node_type extract( const key_type& x );
merge(C++17) splices nodes from another container (public member function),会在source中提取不同key的元素。已到达混合的目的。注意,是“提取”,不会新增所占内存。所以最终source中不同key的元素会被融合进当前map中,自己会保留已有key(在调用这个函数的map中已有)的元素。返回值为空。
(1) (since C++17)
template< class C2>
void merge(std::map<Key, T, C2, Allocator>& source);
(2) (since C++17)
template< class C2>
void merge(std::map<Key, T, C2, Allocator>&& source);
(3) (since C++17)
template< class C2>
void merge(std::multimap<Key, T, C2, Allocator>& source);
(4) (since C++17)
template< class C2>
void merge(std::multimap<Key, T, C2, Allocator>&& source);

set:除了没有那两个函数(try_emplace ,insert_or_assign),其余功能一致,用法类似。

Modifiers
clear lears the contents (public member function)
insert inserts elements or nodes (since C++17) (public member function)
emplace(C++11) constructs element in-place (public member function)
emplace_hint(C++11) constructs elements in-place using a hint (public member function)
erase erases elements (public member function)
swap swaps the contents (public member function)
extract(C++17) extracts nodes from the container (public member function)
merge (C++17) splices nodes from another container (public member function)

查找

map与set这些函数相同;

Lookup 函数原型
count returns the number of elements matching specific key (public member function)匹配key的值,返回值只能是0或1
size_type count (const key_type& k) const;
find finds element with specific key (public member function),返回特定key的元素迭代器,若没有则返回end()
iterator find( const Key& key );
const_iterator find( const Key& key ) const;
equal_range returns range of elements matching a specific key (public member function)返回所有包含key的迭代器范围,左闭右开区间,即左端点是第一个等于key值的元素,第二个是第一个大于key值的元素
pair<const_iterator,const_iterator> equal_range (const key_type& k) const;
pair<iterator,iterator> equal_range (const key_type& k);
lower_bound returns an iterator to the first element not less than the given key (public member function)返回第一个等于key值的元素的迭代器
iterator lower_bound (const key_type& k);
const_iterator lower_bound (const key_type& k) const;
upper_bound returns an iterator to the first element greater than the given key (public member function)返回第一个大于key值的元素的迭代器
iterator upper_bound (const key_type& k);
const_iterator upper_bound (const key_type& k) const;

仿函数

参考文档上写的是observers(设计模式中的观察者模式?)。函数功能都是返回一个函数对象(仿函数,返回的是key的比较关系)。

Observers
key_comp returns the function that compares keys (public member function)返回的是两个key的比较函数
key_compare key_comp() const;
value_comp returns the function that compares keys in objects of type value_type (public member function)返回的是两个value_type对象中key的比较函数,意味着仿函数的参数是两个value_type对象。
std::map::value_compare value_comp() const;

multimap&&multiset

和map、set操作类似。最大的区别在于multimap和multiset可以存放相同key的元素。

Reference

[1]候捷,《STL源码解析》

[2]http://www.cplusplus.com/reference/map/

[3]http://www.cplusplus.com/reference/set/

原文链接: https://www.cnblogs.com/maricat4/p/14710708.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    Map&&Set

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/330464

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月1日 下午5:35
下一篇 2023年3月1日 下午5:36

相关推荐