C++ Set(集合)

简介

  • set 是一个内部自动有序且不含重复元素的容器。
  • set 最主要的作用就是自动去重并按升序排序,适用于需要去重但是又不方便直接开数组的情况。
  • set 中的元素是唯一的,其内部采用“红黑树”实现。

注:本文章只列举 set 在 ACM 中的常见操作,如需了解更多有关 set 内容,请参考 C++官方文档

Set 的基本用法

头文件 #include <set>
需要使用 std 命名空间 using namespace std;

作用方法说明
定义 setset<type> s;type 可以是任何基本类型或者容器
插入元素s.insert(x)将元素插入到集合中
删除元素s.erase(x)移除元素
查找元素s.count(x)判断集合中是否存在该元素
获取元素个数s.size()不会删除队尾元素
清空集合s.clear()删除集合中所有元素

删除元素及注意事项

//删除迭代器器iterator指向的元素
erase(iterator);

//删除迭代器first和second之间的元素
erase(first,second);

//删除元素x
erase(x);

注意:在迭代器遍历时删除元素会使当前迭代器失效!
下面举例说明: ヾ(•ω•`)o

//错误用法:
for(set<int>::iterator it=s.begin();it!=s.end();it++)
{
	if(someConditions)s.erase(it);
}

//正确删除方法一:
for(set<int>::iterator it=s.begin();it!=s.end();)
{
	if(someConditions)s.erase(it++);
	else it++;
}

//正确删除方法二:
for(set<int>::iterator it=s.begin();it!=s.end();)
{
	if(someConditions)it=s.erase(it);
	else it++;
}

二分查找

由于 set 内部元素是有序的,因此可以进行二分查找。

  • lower_bound(key_value) 返回第一个大于等于key_value的迭代器
  • upper_bound(key_value) 返回最后一个大于等于key_value的迭代器

迭代器类型及用法

set只能通过迭代器遍历,即遍历set集合前需先定义一个迭代器:set<type>::iterator it; 然后使用 *it 访问set中的元素。

//循环输出set集合中的元素
for(set<int>::iterator it=s.begin();it!=s.end();it++)
{
	cout<<*it<<endl;
}

其他类型迭代器:

  • s.begin()s.end() 返回 iterator 类型的迭代器。
  • s.rbegin()s.rend() 返回 reverse_iterator 类型的迭代器。
  • s.cbegin()s.cend() 返回 const_iterator 类型的迭代器。
  • s.crbegin()s.crend() 返回 const_reverse_iterator 类型的迭代器。

注:后两种迭代器仅在 C++11 以后的标准中可用。

这些迭代器的用法都很相似:

//正常迭代器
for(set<int>::iterator it=s.begin();it!=s.end();it++) cout<<*it<<endl;
//反向迭代器
for(set<int>::reverse_iterator it=s.begin();it!=s.end();it++) cout<<*it<<endl;
//常量迭代器(只能访问,不可修改)
for(set<int>::const_iterator it=s.begin();it!=s.end();it++) cout<<*it<<endl;
//反向常量迭代器
for(set<int>::const_reverse_iterator it=s.begin();it!=s.end();it++) cout<<*it<<endl;

相关习题详见: NEFU 大一寒假训练十二(set)2020.02.18

<think>好的,用户想了解C++set集合的用法和特性。首先,我需要回忆一下set的基本概念。set是STL中的关联容器,存储唯一元素,且按特定排序规则自动排序。通常用红黑树实现,所以插入、删除、查找的时间复杂度都是O(log n)。这些是基本特性,应该先介绍。 接下来,用户需要具体的使用方法。比如如何定义和初始化set。根据引用[3],set的定义有几种方式:默认构造函数、初始化列表、拷贝构造等。需要举例说明,比如std::set<int> s1;或者用已有容器的一部分初始化。 然后是常用操作,插入元素。引用[2]提到insert和emplace方法,还有emplace_hint。要说明insert返回pair,包含迭代器和是否插入成功的bool。emplace可以直接构造元素,避免临时对象,提高效率。emplace_hint则给出提示位置,可能优化插入速度,但需要正确使用。 关于元素的访问和查找,find方法返回迭代器,如果找不到则返回end()。count可以用来检查元素是否存在,因为set中元素唯一,所以count只能是0或1。这些方法在引用[3]中应该提到。 还有集合操作,比如并集、交集、差集、对称差集。引用[1]中的set_difference,但用户需要知道这些算法在<algorithm>头文件中,需要结合inserter使用。例如求差集时,用std::set_difference,并插入到结果容器中。要提到这些函数的使用方法,以及参数顺序的重要性,比如交换a和b的位置会影响结果。 另外,set的特性包括自动排序和元素唯一性。如果用户插入重复元素,insert会失败,emplace也是。这点需要强调,可能用户在处理数据去重时会用到。 迭代器方面,set支持双向迭代器,可以正向和反向遍历。引用[3]中的例子展示了正向迭代器的使用,应该说明遍历的方法,比如用begin()和end()循环。 性能方面,要提到红黑树的结构保证了操作的复杂度,适用于需要频繁查找和有序输出的场景。比如维护一个有序不重复的集合,或者需要快速判断元素是否存在。 可能用户在实际使用中会遇到的问题,比如自定义排序规则。set默认是升序,但可以通过模板参数改为降序或者自定义比较函数。例如std::set<int, std::greater<int>>。这点在引用[3]中也有提到,需要说明如何修改排序方式。 总结的时候,要分点列出set的特性,如自动排序、唯一元素、高效操作,以及常用方法如插入、删除、查找,集合运算等。确保覆盖用户可能关心的各个方面,并结合引用中的例子具体说明,比如emplace_hint的使用场景和注意事项。 最后,生成相关问题时要围绕set的扩展应用、性能优化、与其他容器的比较,以及高级操作如自定义排序等方面提问,帮助用户深入理解。</think>### C++ set 集合的使用方法与特性 #### 1. 基本特性 - **唯一元素**:set 容器中的元素具有唯一性,重复插入会被自动忽略[^3]。 - **自动排序**:元素按**严格弱序**规则(默认升序)自动排列,底层通过红黑树实现。 - **高效操作**:插入、删除、查找的时间复杂度均为 $O(\log n)$[^3]。 #### 2. 定义与初始化 ```cpp // 默认构造函数(升序) std::set<int> s1; // 初始化列表 std::set<std::string> names = {"James", "Tom"}; // 自定义排序规则(降序) std::set<int, std::greater<int>> s2; ``` #### 3. 常用操作 - **插入元素**: ```cpp auto result = names.insert("Rose"); // 返回pair<iterator, bool> names.emplace("Lucy"); // 直接构造元素,避免临时对象[^2] ``` - **删除元素**: ```cpp names.erase("Tom"); // 通过值删除 names.erase(names.begin()); // 通过迭代器删除 ``` - **查找元素**: ```cpp auto it = names.find("Rose"); // 返回迭代器,未找到则返回end() bool exists = names.count("Tom"); // 返回0或1[^3] ``` #### 4. 集合运算 通过 `<algorithm>` 实现集合操作: ```cpp std::set<int> a{1,2,3}, b{2,3,4}, result; // 差集(a - b) std::set_difference(a.begin(), a.end(), b.begin(), b.end(), std::inserter(result, result.end())); // 结果为{1}[^1] // 对称差集(a ∪ b - a ∩ b) std::set_symmetric_difference(...); ``` #### 5. 性能优化技巧 - **emplace_hint**:若已知插入位置的大致范围,可提升效率: ```cpp auto it = names.emplace_hint(names.begin(), "PreInsert"); // 提示插入位置[^2] ``` - **迭代器失效**:删除操作仅影响被删元素的迭代器,其他迭代器仍有效。 #### 6. 典型应用场景 1. 维护**有序不重复数据集**(如排行榜) 2. 快速**存在性判断**(比vector快100倍以上) 3. 数据去重处理 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值