关联容器map和multimap已经在博客https://blog.csdn.net/Master_Cui/article/details/108690877和https://blog.csdn.net/Master_Cui/article/details/108696599中介绍了
set,multiset和map,multimap的区别就是前两者的key和value都是一个类型的值,是一体的,而后两者的key和value分别是两个类型的值
set和multiset容器中的元素依然按照key进行排序,set中的key不能重复,multiset中的key可以重复,但是排序规则必须是严格弱序的
因为set和multiset中的key和value是同一类型的一个值,一体的,又因为key是const的,所以,set和multiset中的元素也是const的,不能对set和multiset中的元素进行修改
示例
void setconst()
{
int a[]={1,2,3,4,5};
set<int> s(a, a+sizeof(a)/sizeof(*a));
for (set<int>::iterator it=s.begin();
it!=s.end();++it) {
*it=6;
}
}
如果想修改set或者multiset,先将要修改的元素删除,然后再添加新的元素
set和multiset使用前,都要添加头文件#include <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;
template < class T, // multiset::key_type/value_type
class Compare = less<T>, // multiset::key_compare/value_compare
class Alloc = allocator<T> > // multiset::allocator_type
> class multiset;
set和multiset的声明除了名字不同,其余相同,模板参数比map和multimap少了一个key,因为set和multiset的key就是value,value就是key,key的排序方式默认依然是升序
set();//默认构造函数
explicit set (const key_compare& comp, const allocator_type& alloc = allocator_type());//指定排序方式的构造函数
explicit set (const allocator_type& alloc);
//通过迭代器初始化的普通构造函数
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());
//拷贝构造
set (const set& x);
set (const set& x, const allocator_type& alloc);
//列表初始化
set (initializer_list<value_type> il, const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type());
set (initializer_list<value_type> il, const allocator_type& alloc = allocator_type());
set和multiset的构造函数依然是除了名字不同,其余相同
示例
bool comp(int k1, int k2) {return k1>k2;}
void setinit()
{
int a[]={1,2,3,4,5};
set<int> s(a, a+sizeof(a)/sizeof(*a));
for (set<int>::iterator it=s.begin();
it!=s.end();++it) {
cout<<*it<<endl;
}
set<int, bool(*)(int, int)> s2(a, a+sizeof(a)/sizeof(*a), comp);//改写key的排序方式
for (set<int, bool(*)(int, int)>::iterator it=s2.begin();
it!=s2.end();++it) {
cout<<*it<<endl;
}
}
2.set和multiset的赋值
同map。见博客https://blog.csdn.net/Master_Cui/article/details/108690877
3.set和multiset的查找
size_type count (const value_type& k) const;//计算set和multiset容器对象中指定key的元素的个数并返回,
iterator find (const value_type& k);//查找指定key的元素的所在位置,返回该元素的迭代器,如果没有根据key找到该元素,返回尾后迭代器end()
const_iterator find (const value_type& k) const;
iterator lower_bound (const value_type& k);//查找第一个key>=k的元素,返回该元素的迭代器,如果没有根据key找到该元素,返回尾后迭代器end()
const_iterator lower_bound (const value_type& k) const;
iterator upper_bound (const value_type& k);//查找第一个key>k的元素,返回该元素的迭代器,如果没有根据key找到该元素,返回尾后迭代器end()
const_iterator upper_bound (const value_type& k) const;
pair<const_iterator,const_iterator> equal_range (const value_type& k) const;//将lower_bound和upper_bound的迭代器作为一个pair返回
pair<iterator,iterator> equal_range (const value_type& k);
count返回值的情况同map和multimap,find函数也是按插入multiset容器对象顺序,返回对应元素的迭代器
示例
void setserachtest()
{
multiset<int> ms={1,1,1,1,1};
cout<<ms.count(1)<<endl;
multiset<int>::iterator it=ms.begin();
while(it!=ms.end()) {
cout<<*it<<endl;
if (it==ms.find(1)) {
it=ms.erase(it);
}
}
}
4.set和multiset的添加
iterator insert (const value_type& val);//multiset的insert,返回的新插入元素的迭代器
pair<iterator,bool> insert (const value_type& val);//set的insert,和map的情况一样
iterator insert (const_iterator position, const value_type& val);
template <class InputIterator>
void insert (InputIterator first, InputIterator last);
void insert (initializer_list<value_type> il);
添加操作和map,multimap类似,参考博客https://blog.csdn.net/Master_Cui/article/details/108690877和https://blog.csdn.net/Master_Cui/article/details/108696599
5.set和multiset的删除
iterator erase (const_iterator position);
size_type erase (const key_type& k);
iterator erase (const_iterator first, const_iterator last);
删除操作和map,multimap类似,参考博客https://blog.csdn.net/Master_Cui/article/details/108690877和https://blog.csdn.net/Master_Cui/article/details/108696599
6.set和multiset的一般操作
同map。见博客https://blog.csdn.net/Master_Cui/article/details/108690877
7.set和multiset与迭代器失效
除了博客https://blog.csdn.net/Master_Cui/article/details/108690877中说过的使用已被删除元素的迭代器外,还有利用erase函数的返回值更新迭代器,否则,也会出先迭代器失效的情况
void setiteratorfailed()
{
multiset<int> ms={1,1,1,1,1};
for (multiset<int>::iterator it=ms.begin();
it!=ms.end();++it) {
cout<<*it<<endl;
ms.erase(it);
cout<<"-------"<<endl;
}
}
因为没有用erase的返回值更新迭代器,导致it失效,但是之后又对it进行++操作,所以提示尝试对一个失效迭代器自增
即使更新迭代器了,也不要在erase时,同时在for循环中自增迭代器
void setiteratorfailed()
{
multiset<int> ms={1,1,1,1,1};
for (multiset<int>::iterator it=ms.begin();
it!=ms.end();++it) {
cout<<"+++++++"<<endl;
cout<<*it<<endl;
it=ms.erase(it);
cout<<"-------"<<endl;
}
}
之所以会出现迭代器失效的原因,是因为当删除了第5个元素后,迭代器指向的尾后迭代器,此时迭代器已经失效,但是又对迭代器进行自增操作,所以就出现了段错误,因为对一个失效的迭代器自增
解决办法就是将for循环的自增操作删除,因为erase后,迭代器会自动指向被删除元素的下一个元素
for (multiset<int>::iterator it=ms.begin();
it!=ms.end();/*++it*/)
参考
《C++ Primer》
《C++标准库》
http://www.cplusplus.com/reference/set/
欢迎大家评论交流,作者水平有限,如有错误,欢迎指出