在 C++ 里,std::set
属于标准库容器的一种,其特性是按照特定顺序存储唯一的元素。下面为你详细介绍它的常见使用方法:
1. 头文件引入
要使用std::set
,需要在代码中包含相应的头文件:
#include <set>
2. 集合的定义与初始化
// 定义一个存储int类型的空集合,默认按升序排列
std::set<int> s1;// 用初始化列表来初始化集合
std::set<int> s2 = {1, 2, 3};// 借助比较函数,定义一个按降序排列的集合
std::set<int, std::greater<int>> s3 = {3, 1, 2}; // 结果为3, 2, 1// 通过已有集合来初始化新集合
std::set<int> s4(s2);
3. 元素的添加操作
可以使用insert()
方法向集合中添加元素:
std::set<int> s;
s.insert(10); // 集合现在包含元素10
s.insert(20); // 集合现在包含元素10和20
s.insert(10); // 由于元素10已存在,不会重复添加
4. 元素的查找操作
若要查找集合中是否存在某个元素,可使用find()
或count()
方法:
auto it = s.find(20); // 如果找到元素20,it指向该元素;否则it等于s.end()
if (it != s.end()) {std::cout << "找到了元素:" << *it << std::endl;
}bool exists = s.count(20); // 若元素20存在,返回1;否则返回0
5. 元素的删除操作
可以使用erase()
方法删除集合中的元素:
s.erase(20); // 删除元素20
s.erase(s.find(10)); // 通过迭代器删除元素10
s.clear(); // 清空集合中的所有元素
6. 集合的遍历操作
集合支持使用迭代器、范围 for 循环或者 C++20 引入的范围库来遍历元素:
// 使用迭代器遍历
for (auto it = s.begin(); it != s.end(); ++it) {std::cout << *it << " ";
}// 使用范围for循环遍历
for (const auto& element : s) {std::cout << element << " ";
}// 使用C++20的范围库(需要包含<ranges>头文件)
for (auto element : s | std::views::reverse) {std::cout << element << " "; // 逆序输出元素
}
7. 集合的大小与判空
可以通过以下方法了解集合的大小以及判断集合是否为空:
size_t size = s.size(); // 获取集合中元素的数量
bool empty = s.empty(); // 判断集合是否为空
8. 其他实用方法
集合还提供了一些其他有用的方法:
auto lower = s.lower_bound(15); // 返回第一个大于或等于15的元素的迭代器
auto upper = s.upper_bound(15); // 返回第一个大于15的元素的迭代器// 交换两个集合的内容
std::set<int> s5 = {4, 5};
s.swap(s5);
9. 自定义比较函数
对于自定义类型,需要定义比较函数:
struct Person {std::string name;int age;
};// 按照age升序排列
struct Compare {bool operator()(const Person& p1, const Person& p2) const {return p1.age < p2.age;}
};std::set<Person, Compare> people = {{"Alice", 25}, {"Bob", 20}};
10. 多重集合(允许重复元素)
如果需要存储重复元素,可以使用std::multiset
:
std::multiset<int> ms;
ms.insert(10);
ms.insert(10); // 允许插入重复的10
典型应用场景
- 自动对元素进行排序。
- 高效地去重(时间复杂度为 O (log n))。
- 快速查找、插入和删除元素(时间复杂度均为 O (log n))。
注意要点
- 集合中的元素是不可变的,若要修改元素,需先删除该元素,再插入新元素。
- 集合会自动对元素进行排序,因此插入顺序不会被保留。