Files
Data-Structure/STL/STL-Set/README.MD
2025-08-06 18:43:00 +08:00

207 lines
4.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

当然可以!以下是 **C++ STL 中 `set` 的详细介绍和使用方法大全**,包括:
---
## 🧱 1. 基本概念
`std::set` 是一个 **有序集合**,底层实现是 **红黑树RB-tree**
特点如下:
* 所有元素 **自动升序排列(默认 `<`**
* 所有元素 **唯一**,不能重复
* 元素类型必须支持 `<` 操作符(可自定义)
* **查找、插入、删除**操作都是 **O(log n)** 的时间复杂度
---
## 📦 2. 头文件
```cpp
#include <set>
```
---
## 🧪 3. 声明与初始化
```cpp
std::set<int> s1; // 空集合
std::set<int> s2 = {4, 1, 3}; // 初始化,自动排序去重
std::set<std::string> s3{"apple", "banana"};
std::set<int, std::greater<int>> s4; // 降序排列
```
---
## 🧾 4. 常用成员函数汇总
| 函数 | 作用 |
| ------------------ | -------------------------------- |
| `insert(val)` | 插入元素(成功返回 pair\<iterator, true> |
| `emplace(val)` | 就地构造元素,性能比 `insert` 更高 |
| `find(val)` | 返回指向该元素的迭代器,找不到返回 `end()` |
| `count(val)` | 返回该值的数量(对于 set 只能是 0 或 1 |
| `erase(val)` | 删除指定元素 |
| `erase(it)` | 删除指定迭代器处元素 |
| `clear()` | 清空集合 |
| `size()` | 元素个数 |
| `empty()` | 是否为空 |
| `begin(), end()` | 起始、结束迭代器 |
| `lower_bound(val)` | 第一个 `>= val` 的位置 |
| `upper_bound(val)` | 第一个 `> val` 的位置 |
| `equal_range(val)` | 返回一个 pair表示 `[lower, upper)` 区间 |
---
## 🔨 5. 插入与查找示例
```cpp
std::set<int> s;
s.insert(5);
s.insert(3);
s.insert(8);
s.insert(3); // 自动忽略重复
// 查找
if (s.find(3) != s.end()) {
std::cout << "Found 3\n";
}
// 遍历
for (int x : s)
std::cout << x << " "; // 输出3 5 8
```
---
## ⛏ 6. 删除元素
```cpp
s.erase(5); // 删除值为5的元素
auto it = s.find(8);
if (it != s.end()) s.erase(it); // 用迭代器删除
```
---
## ⏬ 7. 自定义排序规则
```cpp
struct MyCmp {
bool operator()(const int &a, const int &b) const {
return a > b; // 降序
}
};
std::set<int, MyCmp> s = {1, 5, 3}; // 输出顺序5 3 1
```
---
## 🌈 8. 自定义结构体作为元素
### ✅ 正确写法:重载 `<`
```cpp
struct Person {
std::string name;
int age;
bool operator<(const Person &other) const {
return age < other.age; // 按 age 排序
}
};
std::set<Person> people;
people.insert({"Tom", 25});
people.insert({"Jerry", 20});
```
---
## 🔄 9. 遍历方式
```cpp
// 方法1范围 for
for (int x : s) std::cout << x << " ";
// 方法2迭代器
for (auto it = s.begin(); it != s.end(); ++it)
std::cout << *it << " ";
```
---
## 🧵 10. lower\_bound / upper\_bound 示例
```cpp
std::set<int> s = {2, 4, 6, 8};
auto lb = s.lower_bound(5); // 指向6
auto ub = s.upper_bound(6); // 指向8
```
---
## 🪄 11. set 和 multiset 区别
| 容器 | 是否允许重复 | 底层实现 |
| ---------- | ------- | ---- |
| `set` | ❌ 不允许重复 | 红黑树 |
| `multiset` | ✅ 允许重复 | 红黑树 |
---
## 📚 12. 常见用法技巧
### 用 set 去重:
```cpp
std::vector<int> v = {1, 2, 2, 3};
std::set<int> s(v.begin(), v.end()); // 自动去重
```
### 用 set 排序:
```cpp
std::set<int> s = {5, 1, 3};
// 自动升序排列1 3 5
```
### 交换两个 set
```cpp
std::set<int> a = {1, 2};
std::set<int> b = {3, 4};
a.swap(b);
```
---
## 🧮 13. 高级操作C++17 起)
```cpp
if (auto [it, ok] = s.insert(10); ok) {
std::cout << "插入成功:" << *it << "\n";
}
```
---
## 🚨 14. 注意事项
* `insert` 不会覆盖已有元素,若想更新值,请先 `erase()``insert()`
* 遍历时 **不要修改元素值**(因为会破坏红黑树结构)
* `set``[]` 操作符不存在(不同于 `map`
---
如需,我还可以为你提供:
* 📘 set 应用实战代码示例
* 🧠 使用场景解析(如 top-k、排名、自动去重等
* 🧩 `unordered_set` 的比较与选择策略
是否要我继续讲 `multiset``unordered_set`