set容器初探索
一、set容器
1.1 set与multiset区别与联系:
-
set 是一个集合容器,其中包含的
元素唯一,集合中的元素按顺序排列。元素插入过程是按规则插入的,所有的元素都会根据元素的键值自动排序,不能指定插入位置。 -
set与multiset都采用
红黑树作为底层容器,set与multiset的底层容器都是自动排序的。红黑树是平衡二叉树,所以插入和删除的操作比vector快。 -
set
不可以直接存取元素 -
multiset与set的区别在于,
multiset允许存储多个相同的元素。 -
不可以直接修改set或multiset容器中的元素值,因为该类型的容器是自动排序的。如果确实需要修改元素值,必须先删除旧元素,再插入新元素。
1.2 set与multiset的默认构造函数
set<int> setInt;
set<float> setFloat;
set<string> setString;
multiset<int> multiInt;
multiset<float> multiFloat;
multiset<string> multiString;
1.3 set与multiset的插入和删除
set与multiset的插入和删除操作都是使用insert函数,set与multiset的插入和删除的函数原型如下:
set.insert(const value_type& val); //插入元素val
set.insert(iterator pos, const value_type& val); //在迭代器指向位置插入元素val
set.erase(elem); //删除容器中值为elem的元素
set.erase(pos); //删除迭代器指向的元素
set.erase(begin(), end()); //删除区间内的元素
1.3.1 插入
set<int> s1;
s1.insert(3);
s1.insert(7);
s1.insert(9);
s1.insert(0);
set<int>::iterator it = s1.begin();
for(it = s1.begin(); it != s1.end(); it++)
{
cout << *it << endl;
}
//输出结果 :0 3 7 9
//set默认是升序排序的
set<int>::reverse_iterator it2;
for(it2 = s1.rbegin(); it2 != s1.rend(); it2++)
{
cout << *it2 << endl;
}
//输出:9 7 3 0
//使用反向迭代器可以倒序排序
1.3.2 删除
使用迭代器删除set容器中的元素:
//删除set容器中的最小值 5
it = s.begin();
s.erase(it);
for(it = s.begin(); it != s.end(); it++)
{
cout << *it << " " ;
}
cout << endl;
//删除set容器中的最大值 100
it = s.end();
it--;
s.erase(it);
cout << "it :"<< *it << endl;
for(it = s.begin(); it != s.end(); it++)
{
cout << *it << " " ;
}
cout << endl;
注意1:不能对end进行解引用* 或者是 ++操作
set<int> s = {5, 9, 37, 100}; // 自动排序为 5,9,37,100
// 步骤1:it指向end()(最后一个元素的下一个位置)
it = s.end(); // it → [100的后面]
// 步骤2:it--,指向最后一个元素
it--; // it → 100
// 步骤3:删除100,erase返回新的end()
it = s.erase(it); // 删除100后,it → [37的后面](即新的end())
// 步骤4:危险操作!解引用end()
cout << *it; // 错误!it现在是end(),不能取它的值
// 有时会崩溃,有时会输出随机数
// 步骤5:更危险操作!对end()执行++
it++; // 错误!标准不允许end()++
// 可能:1.崩溃 2.绕回begin() 3.随机值
cout << *it; // 完全不可预测的结果
注意2:erase()必须使用正向迭代器,不支持反向迭代器。
//使用反向迭代器删除set容器中最后一个元素
set<int>::reverse_iterator rit = s.begin();
s.erase(rit);
//erase() 方法不接受 reverse_iterator,必须使用正向迭代器。
3、三原则
1、end()是禁区
2、不能*end(),不能end()++(不能在悬崖边跳舞)
3、删除元素后要更新迭代器:
删除指定的值:
s.erase(5);
for(it = s.begin(); it != s.end(); it++)
{
cout << *it << " " ;
}
cout << endl;
如果需要删除的元素在set容器中不存在,返回false;如果在返回true。
cout << s.erase(5) << endl; //返回0,因为5已经不在set容器中了
cout << s.erase(9) << endl; //返回1,因为9在set容器中
it = s.erase(it); // 必须接收返回值
操作前检查有效性:
if(it != s.end()) { /* 安全操作 */ }
1.4 set与multiset的拷贝构造与赋值
set与multiset的拷贝构造与赋值函数原型如下:
set(const set& s); //拷贝构造函数
set& operator=(const set& s); //重载等号操作符
set<int> s2(s1); //调用拷贝构造函数
set<int> s3; //调用默认构造函数
s3 = s2;
set<int>::iterator it3;
for(it3 = s3.begin(); it3 != s3.end(); it3++)
{
cout << *it3 << endl;
}
s3.insert(100); //插入元素100
cout << "s3插入100" << endl;
s3.swap(s1); //交换s1和s3的内容
//交换后的s1的内容
cout << "交换后的s1的内容:" << endl;
for(it = s1.begin(); it != s1.end(); it++)
{
cout << *it << " ";
}
cout << endl;
cout << "交换后的s3的内容:" << endl;
for(it3 = s3.begin(); it3 != s3.end(); it3++)
{
cout << *it3 << " ";
}
return 0;

1.5 set与multiset的大小和判空
set.size() //返回set容器中元素的个数
set.empty() //判断set容器是否为空,空返回true,非空返回false
1.6 set与multiset的查找
set.find(elem); //查找elem元素,返回指向elem的迭代器;否则返回set.end()
set.count(elem); //查找elem元素,返回elem元素的个数。set容器中元素都是唯一的,所以返回值为0或1。如果是multiset容器,则可能大于1
set.lower_bound(elem); //返回第一个 >= elem元素的迭代器
set.upper_bound(elem); //返回第一个 > elem元素的迭代器
set.equal_range(elem); //返回一个pair,pair.first为lower_bound(elem),pair.second为upper_bound(elem)

浙公网安备 33010602011771号