C++知识点32——使用C++标准库(关联容器set和multiset的初始化,赋值,查找,添加,删除与迭代器失效)

关联容器map和multimap已经在博客https://blog.csdn.net/Master_Cui/article/details/108690877https://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>

1.set和multiset的声明与初始化

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的查找

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/108690877https://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/108690877https://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/

 

欢迎大家评论交流,作者水平有限,如有错误,欢迎指出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值