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大佬
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/330464
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!