C++中的set容器详解
1. set概述
set是C++ STL中的关联容器,它存储唯一元素 并按特定顺序自动排序。set基于红黑树实现,提供高效的查找、插入和删除操作。
2. 基本特性
- 唯一性:所有元素都是唯一的
- 自动排序:元素总是按指定排序规则排列
- 不可修改元素:元素值不能被直接修改
- 高效操作 :查找、插入、删除的时间复杂度为O(log2n)O(\log_2 n)O(log2n)
3. 头文件与声明
cpp
#include <set>
using namespace std;
set<int> s1; // 空set,默认升序
set<int, greater<int>> s2; // 空set,降序排列
set<string> s3 = {"a", "b"}; // 初始化列表
4. 构造函数与初始化
4.1 默认构造
cpp
set<int> s; // 创建空set
4.2 范围构造
cpp
int arr[] = {1, 2, 3};
set<int> s(arr, arr+3); // 用数组范围构造
4.3 拷贝构造
cpp
set<int> s2(s1); // 拷贝构造
5. 容量操作
5.1 size()
cpp
cout << s.size(); // 返回元素数量
5.2 empty()
cpp
if(s.empty()) {
cout << "Set is empty";
}
5.3 max_size()
cpp
cout << s.max_size(); // 返回set可容纳的最大元素数
6. 修改操作
6.1 insert()
cpp
s.insert(10); // 插入单个元素
s.insert({1, 2, 3}); // 插入多个元素
s.insert(s.begin(), 5); // 带提示插入(不一定提高效率)
6.2 emplace()
cpp
s.emplace(10); // 原地构造元素,比insert更高效
6.3 erase()
cpp
s.erase(10); // 删除值为10的元素
s.erase(s.begin()); // 删除迭代器指向的元素
s.erase(s.begin(), s.end()); // 删除范围元素
6.4 clear()
cpp
s.clear(); // 清空所有元素
7. 查找操作
7.1 find()
cpp
auto it = s.find(10); // 查找元素,返回迭代器
if(it != s.end()) {
cout << "Found: " << *it;
}
7.2 count()
cpp
if(s.count(10)) { // 返回匹配元素的数量(0或1)
cout << "Element exists";
}
7.3 lower_bound() & upper_bound()
cpp
auto lb = s.lower_bound(5); // 返回第一个不小于5的元素
auto ub = s.upper_bound(10); // 返回第一个大于10的元素
7.4 equal_range()
cpp
auto range = s.equal_range(5); // 返回等于5的元素范围
// range.first是lower_bound, range.second是upper_bound
8. 迭代器
8.1 begin() & end()
cpp
for(auto it = s.begin(); it != s.end(); ++it) {
cout << *it << " ";
}
8.2 rbegin() & rend()
cpp
for(auto rit = s.rbegin(); rit != s.rend(); ++rit) {
cout << *rit << " "; // 反向遍历
}
9. 完整示例
cpp
#include <iostream>
#include <set>
using namespace std;
int main() {
// 创建并初始化set
set<int> s = {5, 2, 8, 1, 3};
// 插入元素
s.insert(4);
s.emplace(6);
// 查找元素
if(s.find(3) != s.end()) {
cout << "3 found in set\n";
}
// 删除元素
s.erase(2);
// 遍历set
cout << "Set elements: ";
for(int num : s) {
cout << num << " "; // 自动排序输出: 1 3 4 5 6 8
}
cout << endl;
// 范围查询
auto low = s.lower_bound(3);
auto up = s.upper_bound(5);
cout << "Elements between 3 and 5: ";
for(auto it = low; it != up; ++it) {
cout << *it << " "; // 输出: 3 4 5
}
cout << endl;
// 容量信息
cout << "Size: " << s.size() << endl;
cout << "Is empty: " << (s.empty() ? "Yes" : "No") << endl;
return 0;
}
10. 自定义排序规则
cpp
struct CaseInsensitiveCompare {
bool operator()(const string& a, const string& b) const {
return strcasecmp(a.c_str(), b.c_str()) < 0;
}
};
set<string, CaseInsensitiveCompare> caseInsensitiveSet;
11. 性能提示
- 查找操作优先使用
find()而非count() - 插入大量数据时,考虑预先排序后再构造
set - 需要修改元素值时,应先删除再插入新值
- 使用
emplace()替代insert()可避免不必要的拷贝