set的用法总结

本文详细介绍了C++ STL中的set容器使用方法,包括元素的插入、查找、删除,以及如何进行集合运算如并集、交集、差集和对称差等。同时,讲解了lower_bound和upper_bound函数的使用技巧。

set<int> s;

插入元素

s.insert(x);

迭代器循环

for(set<int>::iterator it=s.begin();it!=s.end();it++)

cout<<*it<<" ";

使用size函数获取集合中的元素个数

s.size()

使用find函数查找元素是否存在

s.find(x)!=s.end()  则元素存在

count() 用来查找set中某个某个键值出现的次数。这个函数在set并不是很实用,因为一个键值在set只可能出现0或1次,这样就变成了判断某一键值是否在set出现过了

两个集合的并集

set<int> s1;

set<int> s2;

set_union(s.begin(),s.end(),s1.begin(),s1.end(),insert_iterator<set<int> >(s2,s2.begin()));

两个集合的交集

set_intersection(s.begin(),s.end(),s1.begin(),s1.end(),insert_iterator<set<int> >(s2,s2.begin());

两个集合的差集

set_difference(s.begin(),s.end(),s1.begin(),s1.end(),insert_iterator<set<int> >(s2,s2.begin());

两个集合的对称差

A并B-A交B

set_symmetric_difference(s.begin(),s.end(),s1.begin(),s1.end(),insert)iterator<set<int> > (s2,s2.begin());

upper_bound&lower_bound函数

用法: 
lower_bound(起始位置起始位置+查找的最大长度查找的元素,(cmp))- 数组指针名(数组名)

upper_bound类似

使用之前确保数组有序,lower_bound使用时数组应该是非降序,而upper_bound使用时数组应该是非升序,

最后别忘了减去数组名,因为返回的是一个地址

<think>我们被要求总结C++中set用法。根据引用[1]和引用[2]的信息,以及我们对C++ set的了解,可以总结如下: 1. set是C++ STL中的关联容器,它存储唯一元素(没有重复),并且元素自动排序(默认升序)。 2. set内部实现通常是红黑树(一种平衡二叉搜索树),因此插入、删除和查找操作的时间复杂度都是O(log n)。 3. set的声明:需要包含头文件<set>,然后使用模板类,可以指定元素类型、比较函数(可选)和分配器(可选)。 例如:`set<int> s;` 或者自定义比较函数的情况:`set<node, cmp> s;`(其中node是自定义类型,cmp是比较函数或仿函数) 4. 基本操作: - 插入:`insert(element)` - 删除:`erase(element)` 或 `erase(iterator)` - 查找:`find(element)` 返回迭代器,如果没找到则返回`end()` - 大小:`size()` - 清空:`clear()` 5. 遍历:可以使用迭代器(包括范围for循环)进行遍历,遍历的结果是按排序顺序的。 6. 自定义排序:对于自定义类型(如结构体),需要定义比较规则。可以通过重载<运算符,或者提供仿函数(函数对象)作为set的第二个模板参数。 引用[1]中给出了一个结构体作为set元素的例子。结构体node有两个成员a和b,并且重载了<运算符(注意:这里重载的规则是a>W.a,所以实际上set会按照a的降序排列,因为当当前元素的a大于比较元素的a时,认为当前元素更小,所以排在前面?这里需要解释一下)。 需要注意的是,在重载<运算符时,必须满足严格弱序。在引用[1]的例子中,重载定义为`return a>W.a;`,这意味着当当前元素的a大于比较元素的a时,返回true(即认为当前元素小于比较元素),因此set将按a的降序排列。 另外,引用[2]提到set的声明模板参数: ```cpp template < class T, class Compare = less<T>, class Alloc = allocator<T> > class set; ``` 其中Compare默认是less<T>,它是基于<运算符的。如果我们想改变排序规则,可以自定义一个比较函数或仿函数。 下面我们总结用法,并给出示例代码。 ### set的基本用法总结: 1. **包含头文件** ```cpp #include <set> using namespace std; ``` 2. **声明set** ```cpp set<int> s1; // 存储int的set,默认升序 set<char> s2; ``` 3. **插入元素** ```cpp s1.insert(10); s1.insert(20); ``` 4. **删除元素** ```cpp s1.erase(10); // 删除值为10的元素 ``` 5. **查找元素** ```cpp auto it = s1.find(20); if (it != s1.end()) { cout << "Found: " << *it << endl; } ``` 6. **遍历set** - 使用迭代器: ```cpp for (set<int>::iterator it = s1.begin(); it != s1.end(); it++) { cout << *it << " "; } ``` - 使用范围for循环(C++11): ```cpp for (auto x : s1) { cout << x << " "; } ``` 7. **自定义排序规则** - 方法1:在自定义类型中重载<运算符(如引用[1]的例子) - 方法2:使用仿函数(函数对象) ```cpp struct cmp { bool operator() (const node& a, const node& b) const { return a.a > b.a; // 按a降序 } }; set<node, cmp> s; ``` 8. **其他常用函数** - `s.size()`:返回元素个数 - `s.empty()`:判断是否为空 - `s.clear()`:清空set ### 示例代码(自定义结构体): ```cpp #include <iostream> #include <set> using namespace std; struct node { int a, b; // 方法1:重载<运算符 bool operator< (const node& other) const { // 按a升序:如果a相同,可以再按b排序 if (a == other.a) return b < other.b; return a < other.a; } }; int main() { set<node> s; s.insert({1, 2}); s.insert({3, 4}); s.insert({2, 5}); s.insert({1, 3}); // 这个a=1,b=3会和上面的{1,2}比较,因为a相同,然后按b升序,所以{1,2}在前,{1,3}在后 for (auto n : s) { cout << n.a << " " << n.b << endl; } return 0; } ``` 输出: ``` 1 2 1 3 2 5 3 4 ``` ### 注意事项: - 在set中插入的元素是唯一的,如果插入重复元素,set会忽略该插入操作。 - set的迭代器是只读的(const_iterator),不能通过迭代器修改元素的值(因为修改元素可能破坏内部的有序性)。但是可以删除元素再插入新元素。 - 使用自定义类型时,必须保证比较规则满足严格弱序(strict weak ordering)。 §§相关问题§§ 1. C++ set和unordered_set有什么区别? 2. 如何在set中存储自定义类型并自定义排序规则? 3. set的insert函数返回值是什么? 4. set的查找操作有哪些方法?性能如何? </think>### C++ `std::set` 用法总结 `std::set` 是 C++ STL 中的有序关联容器,基于红黑树实现,具有自动排序和元素唯一性的特性[^2]。以下是核心用法总结: #### 1. **基本特性** - **自动排序**:元素默认按升序排列(可自定义排序规则) - **元素唯一**:不允许重复值 - **时间复杂度**:增删查操作均为 $O(\log n)$ #### 2. **头文件与声明** ```cpp #include <set> using namespace std; // 基本声明(默认升序) set<int> intSet; // 自定义类型声明(需重载<运算符) struct Node { int a, b; bool operator<(const Node& other) const { return a > other.a; // 按a降序排列 } }; set<Node> customSet; // 自定义排序规则[^1] ``` #### 3. **核心操作** | **操作** | **代码示例** | **说明** | |------------------|----------------------------------|------------------------------| | 插入元素 | `s.insert(value)` | 插入新元素 | | 删除元素 | `s.erase(value)` | 删除指定元素 | | 查找元素 | `auto it = s.find(value)` | 返回迭代器(未找到则返回`s.end()`) | | 检查元素存在 | `s.count(value)` | 存在返回1,否则0 | | 获取大小 | `s.size()` | 元素数量 | | 清空集合 | `s.clear()` | 移除所有元素 | #### 4. **遍历方式** ```cpp // 传统迭代器遍历 for(auto it = s.begin(); it != s.end(); it++) { cout << *it << " "; } // 范围for循环(C++11) for(const auto& item : s) { // 使用引用避免拷贝 cout << item << " "; } ``` #### 5. **自定义排序规则** 两种实现方式: ```cpp // 方式1:重载<运算符(见前文Node示例)[^1] // 方式2:使用仿函数 struct CustomCompare { bool operator()(const Node& x, const Node& y) const { return x.b < y.b; // 按b成员升序 } }; set<Node, CustomCompare> customSet; ``` #### 6. **特殊方法** - **边界查询**: ```cpp auto lower = s.lower_bound(10); // ≥10的第一个元素 auto upper = s.upper_bound(20); // >20的第一个元素 ``` - **范围构造**: ```cpp vector<int> vec = {5,3,7}; set<int> s(vec.begin(), vec.end()); // {3,5,7} ``` #### 7. **使用场景** - 需要自动排序的唯一元素集合 - 频繁查找操作的场景 - 需要按顺序遍历元素的场景
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值