map and set
关联式结构和键值对
map and set
关联式结构
1.关联式结构:也是用来存储数据的,但是与序列式结构不同的是,关联式结构存储的是键值对结构在数据检索时比序列式容器的效率更高。
2.
①:键值对:用来表示一种具有一一对应的关系一种结构,这个结构一般有两个类型,分别为<key,value>,其中key是代表键值,value代表与键值对应的信息。(其中key是底层的一种标志,我们将value与key保存在一起,检索时,通过找到key从而找到了与其对应的value)
②:在底层,键值对用pair来表示:其内部的实现结构如下代码:
template<class T1,class T2 >
struct pair
{
typedef T1 first_type;
typedef T2 second_type;
T1 first;
T2 second;
pair(): first(T1()), second(T2())
{}
pair(const T1& a, const T2& b): first(a), second(b)
{}
};
3.树形结构的关联式容器:map,set,multimap,multiset.
其中他们的共同点是:底层的实现都是用红黑树来实现的。
其中mulitmap和mulitset操作方式与map和set相同,但是不同的是mulitmap和mulitset中可以存储重复元素。
set
1.介绍:
- 按照一定次序存储数据的容器。
- 在set中,元素value也就是key,比较的顺序也是按照value来比较的,并且value插入后就不能修改,但是可以进行删除。
- 在set容器内部,是按照升序排序排序的。
- set容器通过访问key的数据的速度比unordered_set的速度慢,但是它可以按照顺序对数据进行直接迭代。
- set的底层是通过红黑树实现的。
注意:
- set与map/multimap,不同,set中存储的时候只需存储value就可以了,但是其底层的存储结构是<value,value>。
- set中插入元素的时候,只需插入value即可,不需要构造键值对。
- set元素不可以重复,但是mulitset的元素可以重复。
- 使用set的迭代器去遍历时,会得到一串有序的数据。
- set中默认是按照升序排序的。
- set中的元素不可修改。
- 底层通过红黑树实现,所以搜索效率为(log2(N))。
2.set的使用:
①:set的参数模板:
template<class Key, //插入的数据
class Pred = less<Key>,//默认按照升序进行排序
class A = allocator<Key>//空间配置器,用来向底层申请空间
>
②:set函数的使用:
1.set的构造:
set (const Compare& comp = Compare(), const Allocator &= Allocator() );//构造空的set
set (InputIterator first, InputIterator last, const Compare&
comp = Compare(), const Allocator& = Allocator() );//使用迭代器来构造set其中,构造的是区间[frist,end)中的数据。
set ( const set<Key,Compare,Allocator>& x); //拷贝构造
2.set的迭代器:
begin() //容器首元素的位置
end() //容器末尾元素的位置
rbegin() //容器末尾元素的位置
rend() //容器首元素的位
//其中rbegin()和rend()的迭代器与正向迭代器相反。
3.set的容量:
bool empty () const//检测set是否为空,空返回true,否则返回true
size_type size() const //返回set中有效元素的个数
4.set的修改:
pair<iterator,bool> insert (const value_type& x)//向set中插入数据,其中bool返回是否插入成功,x为插入的数据,iterator为新插入的数据的位置。
void erase (iterator position)//删除set中当前迭代器所指的位置(postion的位置)
size_type erase (constkey_type& x)//删除数据为x的位置。
void erase (iterator first,iterator last)//删除[first,lase)区间的数据
void swap (set<Key,Compare,Allocator>&st);//交换两个set中的元素
void clear ()//清楚set中的所有数据。
iterator find (constkey_type& x) const//寻找值为X的位置,返回其迭代器,如果没找到,返回end();
size_type count (const key_type& x) const//查找set中值为x的数据的数量。
map
1.介绍:
- map是关联式容器,是按照特等次序(经过key的比较),来存储<key,value>这对键值对的。
- 在map中,键值key主要是用来比较来确定位置的,而值value主要是存储与键值key对应的数据。它俩的数据类型可能不同(主要是看需求),并且在内部,他们是通过pair绑在一起的。
- 在内部,map中数据的此时是按照键值来排序的,如果没有顺序的安排,默认是按照升序的次序排序。
- map中通过键值访问的数据通常来说比unordered_map慢,但是map可以按顺序对元素进行直接迭代。(并且迭代的时候,我们会得到一个有序的数据)
- map中重载的[],所以我们可以根据下元素的下标去对数据进行直接访问。
- map底层的实现是通过红黑树来实现的。
2.map的使用
①:map的参数:
在底层map的所需要的类为:
template<class Key, //存储的是键值
class T, //存储的是与键值对应的数据
class Pred = less<Key>, //默认的比较是按从小到大来按顺序比较的
class A = allocator<T> //空间配置器,用来在底层申请空间。
>
②:map函数的接口:
1.构造:
map() //构造一个空的map
map(const map& x);//拷贝构造一个与x相同的map
map(const value_type *first, const value_type *last,
const Pred& comp = Pred(),const A& al = A());//通过迭代器构造
2.迭代器:
begin() //容器首元素的位置
end() //容器末尾元素的位置
rbegin() //容器末尾元素的位置
rend() //容器首元素的位
//其中rbegin()和rend()的迭代器与正向迭代器相反。
其中还用const类型的迭代器,就是在上述的接口前面加上c即可。
3.容量与元素的访问:
bool empty ( ) const//检测map是否为空,如果为空返回true否则返回false
size_type size() const//返回map中的有效数量,意思为只返回存储数据的节点数量
mapped_type& operator[] (const key_type& k)//map中重载了[],可以根据下表去访问map中的元素。
上述重载[]使用的时候需要注意的是,如果寻找的下标的数不在map中,那么map就会创建以一个这样的数插入map中。
4.元素的修改:
pair<iterator,bool> insert (const value_type& x )//插入操作,在map中新插入一个元素,其中bool返回是否插入成功,x表示的是一个键值对,iterator代表的是新插入的位置。
void erase (iterator position) //删除迭代器目前指在的位置。
size_type erase (const key_type& x)//删除map容器中键值等于x的数
void erase (iterator first,iterator last)//删除区间[frist,end)中的元素
void swap (map<Key,T,Compare,Allocator>&mp )//交换两个map
void clear ()//清空容器中的元素
iterator find (const key_type& x)//查找map中键值为x的数,成功返回该元素的迭代器,没有返回end()。
size_type count (const key_type& x) const//查询map中键值为x的数量(也可也用来检测map中是否有这个数据)
5.总结:
- map中的元素是键值对。
- map中的key是唯一的并且不能修改(由于底层是红黑树结构,如果修改那么就会破坏红黑树的性质,但是可以删除)
- 默认是按照升序的方式排序的。
- 如果使用迭代器对map中的元素进行迭代,那么就会得到一个有序的数据
- 底层实现为红黑树,查询效率高(log2(N))。
- 支持[]操作符,可以进行插入查找。
其中:对于set和map注意的是,如果想要进行降序排序,只需在其类型后面加上降序的函数即可,例子如下:
set<int,greater<int>> s;
map<int,string,greater<int>>;
//但是在使用的时候需要加上头文件:
#include<functional>