47 C++ STL模板库16-容器8-关联容器-集合(set)多重集合(multiset)
STL模板库-容器8-关联容器-集合(set)多重集合(multiset)
文章目录
- STL模板库-容器8-关联容器-集合(set)多重集合(multiset)
- 1. 构造函数与容量函数
- 1. 函数说明
- 2. 用法示例
- 3. 关键差异总结
- 2. 迭代器操作
- 1. 函数说明
- 2. 用法示例
- 3. 元素插入函数
- 1. 函数说明
- 2. 用法示例
- 3. 关键解析
- 4. 元素删除函数
- 1. 函数说明
- 2. 用法示例
- 关键解析
- 5. 查找与范围查询
- 1. 函数说明
- 2. 用法示例
- 6. 比较器与交换操作
- 1. 函数说明
- 2. 用法示例
- 7. `set` 与 `multiset`关键差异
- 8. 关键特性
- 9. 完整示例
集合(set)多重集合(multiset) 是STL模板库里面的一种关联容器。
元素是有序排列(默认升序),集合不能重复。多重集合元素可以重复。两者的使用方法相同,
所有操作定义在头文件
<set>
中。
1. 构造函数与容量函数
1. 函数说明
函数签名 | 功能说明 |
---|---|
set() / multiset() | 默认构造函数,创建空容器 |
set(const Comp& comp) | 使用自定义比较器 comp 创建空容器 |
set(InputIt first, InputIt last) | 通过迭代器范围 [first, last) 构造容器 |
set(initializer_list<T> il) | 通过初始化列表构造容器 |
size_type size() const | 返回当前元素数量 |
bool empty() const | 检查容器是否为空 |
size_type max_size() const | 返回系统支持的最大元素数量 |
2. 用法示例
-
构造函数
-
默认构造函数
set<int> s1; // 创建空 set(自动去重) multiset<string> ms1; // 创建空 multiset(允许重复)
-
迭代器范围构造
vector<int> data = {3, 1, 1, 4}; set<int> s3(data.begin(), data.end()); // s3 = {1, 3, 4}(去重+排序) multiset<int> ms3(data.begin(), data.end());// ms3 = {1, 1, 3, 4}(保留重复)
-
初始化列表构造
set<string> s4 = {"apple", "banana", "apple"}; // s4 = {"apple", "banana"} multiset<float> ms4 = {1.1, 2.2, 1.1}; // ms4 = {1.1, 1.1, 2.2}
-
自定义比较器构造
#include <iostream> #include <set> #include <vector> using namespace std;int main() {// ======== 1. 定义降序比较器 ========auto desc = [](auto a, auto b) { return a > b; }; // 通用降序比较器(C++14起支持auto参数)// ======== 2. 创建降序容器 ========// 降序set(存储整数)set<int, decltype(desc)> numSet(desc);// 降序multiset(存储字符)multiset<char, decltype(desc)> charMultiset(desc);// ======== 3. 插入测试数据 ========vector<int> numbers = {3, 1, 4, 1, 5, 9, 2}; // 带重复数字 vector<char> chars = {'c', 'a', 'b', 'a', 'd'}; // 带重复字符for (int num : numbers) {numSet.insert(num); // set自动去重 }for (char c : chars) {charMultiset.insert(c); // multiset保留重复 }// ======== 4. 验证输出结果 ========cout << "降序set的元素(自动去重): ";for (int n : numSet) {cout << n << " "; // 输出:9 5 4 3 2 1}cout << "\n\n降序multiset的元素(保留重复): ";for (char c : charMultiset) {cout << c << " "; // 输出:d c b a a }// ======== 5. 额外验证操作 ========cout << "\n\n验证操作:";cout << "\n1. set是否包含5? " << (numSet.find(5) != numSet.end() ? "是" : "否");//是cout << "\n2. multiset中'a'的数量: " << charMultiset.count('a'); //2cout << "\n3. set的首元素: " << *numSet.begin(); //9cout << "\n4. multiset的尾元素: " << *charMultiset.rbegin() << endl;//areturn 0; }
-
-
容量函数
-
获取元素数量
size()
std::set<int> s5 = {5, 2, 8}; std::cout << s5.size()<<'\n'; // 输出:3(唯一元素计数)std::multiset<char> ms5 = {'a', 'a', 'b'}; std::cout << ms5.size()<<'\n'; // 输出:3(包含重复元素)
-
检查容器是否为空
empty()
std::set<double> s6; if (s6.empty()) { // 条件成立 std::cout << "s6 is empty \n"; }std::multiset<int> ms6 = {10}; if (!ms6.empty()) { // 条件成立 std::cout << "ms6 has data \n"; }
-
获取最大容量
max_size()
std::set<long> s7; std::cout << "Max elements: " << s7.max_size()<<std::endl; // 示例输出:Max elements: 461168601842738790(系统相关)std::multiset<std::string> ms7; std::cout << "Max strings: " << ms7.max_size()<<std::endl; // 示例输出:Max strings: 288230376151711743
-
3. 关键差异总结
场景 | set 行为 | multiset 行为 |
---|---|---|
初始化重复元素 | 自动去重 ({1,1,2} → {1,2} ) | 保留重复 ({1,1,2} → {1,1,2} ) |
size() 返回值 | 唯一元素数量 | 所有元素总数(含重复) |
比较器作用 | 同时控制排序和唯一性 | 仅控制排序(不影响重复性) |
所有函数时间复杂度:O(1)(常量时间操作)
底层实现:红黑树(Red-Black Tree)保证元素有序性
2. 迭代器操作
1. 函数说明
函数签名 | 功能说明 |
---|---|
iterator begin() noexcept | 返回指向首元素的正向迭代器 |
iterator end() noexcept | 返回尾后位置的正向迭代器 |
const_iterator cbegin() const | 常量版本 begin() (C++11) |
reverse_iterator rbegin() | 返回指向最后一个元素的反向迭代器 |
reverse_iterator rend() | 返回反向尾后迭代器 |
2. 用法示例
#include <iostream>
#include <set>
using namespace std;int main() {// 初始化容器 set<int> nums = {30, 10, 20}; // {10, 20, 30}(自动排序)multiset<char> chars = {'c', 'a', 'b'}; // {'a', 'b', 'c'}// ================== 正向迭代器 ==================cout << "1. 正向遍历set: ";for (auto it = nums.begin(); it != nums.end(); ++it) {cout << *it << " "; // 输出:10 20 30 }cout << "\n\n2. 常量迭代器遍历multiset: ";for (auto it = chars.cbegin(); it != chars.cend(); ++it) {// *it = 'x'; // ❌ 错误:常量迭代器禁止修改cout << *it << " "; // 输出:a b c }// ================== 反向迭代器 ==================cout << "\n\n3. 反向遍历set: ";for (auto rit = nums.rbegin(); rit != nums.rend(); ++rit) {cout << *rit << " "; // 输出:30 20 10}// ================== 边界操作 ==================cout << "\n\n4. 首尾元素访问:";cout << "\n set首元素: " << *nums.begin(); // 10 cout << "\n set尾后位置: " << (nums.end() == next(nums.begin(), 3) ? "true" : "false"); // truecout << "\n multiset反向首元素: " << *chars.rbegin(); // c return 0;
}
📊 输出结果
1. 正向遍历set: 10 20 302. 常量迭代器遍历multiset: a b c3. 反向遍历set: 30 20 104. 首尾元素访问:set首元素: 10set尾后位置: truemultiset反向首元素: c
特性:迭代器双向遍历,修改元素会导致迭代器失效(需删除后重新插入)。
3. 元素插入函数
1. 函数说明
函数签名 | 功能说明 | 返回值差异说明 |
---|---|---|
pair<iterator, bool> insert(const T& value) | 插入单个元素(set 限制唯一性) | set :返回 (iter, 插入成功) multiset :返回 iter (始终成功) |
iterator insert(iterator hint, const T& value) | 通过位置提示 hint 优化插入效率 | 两者均返回新元素迭代器 |
void insert(InputIt first, InputIt last) | 插入迭代器范围内的元素 | 无返回值 |
template <class... Args> emplace(Args&&... args) | 原位构造元素(避免拷贝) | 返回值同普通 insert() |
iterator emplace_hint(const_iterator hint, Args&&... args) | 带位置提示的原位构造 | 返回新元素迭代器 |
2. 用法示例
#include <iostream>
#include <set>
#include <vector>
using namespace std;int main() {// 示例1:插入单个元素 set<int> s1;auto [it1, inserted] = s1.insert(10); // ✅ 插入成功 cout << "插入10: " << (inserted ? "成功" : "失败") << endl; // 输出:成功 auto [it2, ignore] = s1.insert(10); // ❌ 重复插入cout << "再次插入10: " << (ignore ? "成功" : "失败") << endl; // 输出:失败 // 示例2:位置提示插入 (hint)multiset<char> ms1;auto hint = ms1.begin();hint = ms1.insert(hint, 'a'); // 在开头插入hint = ms1.insert(++hint, 'c'); // 在第二个位置插入ms1.insert(hint, 'b'); // 在中间插入cout << "multiset: ";for (char c : ms1) cout << c << " "; // 输出:a b c// 示例3:范围插入 vector<int> nums = {5, 3, 8};s1.insert(nums.begin(), nums.end()); // 批量插入cout << "\nset: ";for (int n : s1) cout << n << " "; // 输出:3 5 8 10// 示例4:原位构造 (emplace)set<string> s2;auto [it3, success] = s2.emplace("apple"); // 避免临时对象拷贝 s2.emplace(3, 'x'); // 构造字符串 "xxx"// 示例5:带提示的原位构造multiset<string> ms2;auto pos = ms2.cbegin();ms2.emplace_hint(pos, "first"); // 开头插入 ms2.emplace_hint(ms2.end(), "last"); // 末尾插入return 0;
}
3. 关键解析
-
唯一性控制
set<int> s; s.insert(5); // 返回 (iter, true) s.insert(5); // 返回 (existing_iter, false)
set
通过返回值告知插入结果multiset
始终返回新元素迭代器
-
原位构造优势
// 传统insert需构造临时对象 s.insert(MyComplexClass(1,2,3)); // emplace直接传递构造参数 s.emplace(1,2,3); // 避免额外拷贝/移动
- 对大型对象性能提升显著
- 语法更简洁(C++11 起推荐使用)
-
范围插入性能
vector<int> big_data(10000); // 低效方式(单次插入) for (int n : big_data) s.insert(n); // O(n log n)// 高效方式(批量插入) s.insert(big_data.begin(), big_data.end()); // O(n log n) 但常数更优
4. 元素删除函数
1. 函数说明
函数签名 | 功能说明 | 返回值说明 |
---|---|---|
size_type erase(const key_type& key) | 删除所有键等于 key 的元素 | set :0 或 1multiset :删除数量 |
iterator erase(const_iterator pos) | 删除迭代器 pos 指向的元素 | 返回被删元素的下一个迭代器 |
iterator erase(const_iterator first, last) | 删除范围 [first, last) 内的元素 | 返回 last |
void clear() noexcept | 清空容器 | - |
2. 用法示例
-
按值删除
erase(key)
#include <iostream> #include <set>int main() {std::set<int> s = {5, 2, 8};std::multiset<char> ms = {'a', 'b', 'a', 'c'};// 删除 set 中的 2(存在)std::size_t s_count = s.erase(2); // s_count=1,s={5,8}// 删除 multiset 中的 'a'(存在2个)std::size_t ms_count = ms.erase('a'); // ms_count=2,ms={'b','c'}std::cout << "set删除数量: " << s_count << "\nmultiset删除数量: " << ms_count; }
-
迭代器删除
erase(pos)
#include <set>int main() {std::set<int> s = {10, 20, 30};auto it = s.find(20); // 定位元素 if (it != s.end()) {// 删除迭代器指向元素,返回下一个元素的迭代器 auto next_it = s.erase(it); // s={10,30}, next_it指向30 }// 错误案例:删除 end() 迭代器(未定义行为)// s.erase(s.end()); // ❌ 崩溃风险 }
-
范围删除
erase(first, last)
#include <set>int main() {std::multiset<int> ms = {5, 3, 9, 1, 3};//multiset会自动排序,插入后的顺序是升序:{1, 3, 3, 5, 9}。// 删除第2个到倒数第2个元素([3,3,5])auto first = ++ms.begin(); // 指向第二个元素3 auto last = std::prev(ms.end()); // 指向倒数第1个元素9ms.erase(first, last); // 保留首尾,ms={1,9}ms.clear();// 清空容器等效操作 // ms.erase(ms.begin(), ms.end());}
关键解析
-
multiset
删除特异性std::multiset<int> ms = {5,5,5}; ms.erase(5); // 删除所有5 → ms空 ms.erase(ms.find(5)); // 只删除第一个5 → ms={5,5}
-
性能优化技巧
// 批量删除比单次循环更高效 std::set<int> data = {/*大量元素*/}; data.erase(data.begin(), data.find(100)); // 删除前段元素
5. 查找与范围查询
1. 函数说明
函数签名 | 功能说明 |
---|---|
iterator find(const key_type& key) | 返回首个键等于 key 的迭代器(未找到返回 end() ) |
size_type count(const key_type& key) const | 返回匹配 key 的元素数量(set 为 0/1;multiset 可 ≥1) |
bool contains(const key_type& key) const | 检查是否存在键 key (C++20 引入) |
iterator lower_bound(const key_type& key) | 返回首个 ≥ key 的元素的迭代器 |
iterator upper_bound(const key_type& key) | 返回首个 > key 的元素的迭代器 |
pair<iter, iter> equal_range(const key_type& key) | 返回匹配 key 的范围 [lower_bound, upper_bound) |
2. 用法示例
-
find()
- 精确查找元素#include <set> #include <iostream>int main() {std::set<int> s = {10, 20, 30};auto it = s.find(20); // 查找元素20 if (it != s.end()) {std::cout << "Found: " << *it; // 输出: Found: 20 } else {std::cout << "Not found";} }
特性:
- 返回首个匹配元素的迭代器
- 时间复杂度:
O(log n)
- 未找到时返回
end()
(需显式检查)
-
count()
- 统计元素数量std::multiset<char> ms = {'a', 'b', 'a', 'c'}; std::cout << "a的数量: " << ms.count('a'); // 输出: 2 std::cout << "z的数量: " << ms.count('z'); // 输出: 0
对比:
容器类型 返回值范围 典型用途 set
0 或 1 验证元素存在性 multiset
≥0 的整数 统计重复元素数量 -
contains()
- 存在性检查(C++20)std::set<std::string> cities = {"Tokyo", "Paris"}; if (cities.contains("Paris")) { // 直接返回bool std::cout << "包含巴黎"; // 输出 }
优势:
- 语法更直观(替代
find() != end()
模式) - 性能等同
find()
(编译器优化) - 专为存在性检查场景设计
- 语法更直观(替代
-
lower_bound()
/upper_bound()
- 范围定位std::multiset<int> scores = {60, 70, 80, 90, 90, 100}; auto low = scores.lower_bound(80); // 首个≥80的元素 → 80 auto high = scores.upper_bound(90); // 首个>90的元素 → 100 // 输出[80,90]区间值 for (auto it = low; it != high; ++it) std::cout << *it << " "; // 输出: 80 90 90
范围定位数学关系:
[lower_bound,upper_bound)={x∣key ≤ x < key+1 }
-
equal_range()
- 获取等价范围auto [first, last] = scores.equal_range(90); // C++17结构化绑定 std::cout << "90分人数: " << std::distance(first, last); // 输出: 2
- 返回
pair<iterator, iterator>
- 特别适合
multiset
的批量操作
- 返回
📊 核心函数对比表
函数 | 返回值类型 | 最佳场景 | 时间复杂度 |
---|---|---|---|
find(key) | 单个迭代器 | 精确获取元素 | O(log n) |
count(key) | 整数 | 统计数量 | O(log n + k) |
contains(key) | bool | 快速存在性检查(C++20+) | O(log n) |
lower_bound(key) | 迭代器 | 范围查询起点 | O(log n) |
upper_bound(key) | 迭代器 | 范围查询终点 | O(log n) |
equal_range(key) | 迭代器对 | 批量处理相同键元素 | O(log n) |
6. 比较器与交换操作
1. 函数说明
函数签名 | 功能说明 |
---|---|
key_compare key_comp() const | 返回键比较器对象(如 less<T> ) |
value_compare value_comp() const | 返回值比较器(等同于 key_comp() ) |
void swap(set& other) | 交换两个容器内容(常数时间复杂度) |
2. 用法示例
-
key_comp()
- 获取键比较器#include <set> #include <iostream>int main() {std::set<int, std::less<int>> s = {5, 3, 9}; // 默认比较器为 std::less // 获取键比较器对象 auto comp = s.key_comp(); // 等价于 std::less<int>// 使用比较器判断元素顺序 std::cout << std::boolalpha << "5 < 10? :" << comp(5, 10) // 输出 true << "\n10 < 5? :" << comp(10, 5); // 输出 false // 验证排序规则 for (int x : s) std::cout << x << " "; // 输出 3 5 9(按升序排列) }
关键说明:
- 比较器类型由模板参数决定(默认为
std::less<T>
) - 可用于自定义排序(如改为
std::greater<T>
则容器逆序存储)
- 比较器类型由模板参数决定(默认为
-
value_comp()
- 获取值比较器#include <set> #include <string>int main() {// 定义按字符串长度排序的集合 struct LengthCompare {bool operator()(const std::string& a, const std::string& b) const {return a.length() < b.length();}};std::multiset<std::string, LengthCompare> ms = {"Apple", "Banana", "Cherry"};// 获取值比较器(与 key_comp 等价)auto v_comp = ms.value_comp(); // 即 LengthCompare 对象 // 比较两个值 bool result = v_comp("C++", "Python"); // 3 < 6 → true }
技术要点:
- 在
set/multiset
中,value_compare
与key_compare
完全等价 - 此函数主要用于兼容性设计(与
map
的行为对齐)
- 在
-
swap()
- 容器内容交换#include <set> #include <iostream>int main() {std::set<int> s1 = {10, 20};std::set<int> s2 = {30, 40, 50};// 交换前状态 std::cout << "交换前: s1大小=" << s1.size() // 2 << ", s2大小=" << s2.size(); // 3 s1.swap(s2); // 常数时间操作(仅交换内部指针)// 交换后验证 std::cout << "\n交换后: s1元素: ";for (int x : s1) std::cout << x << " "; // 30 40 50 std::cout << "\ns2元素: ";for (int x : s2) std::cout << x << " "; // 10 20 }
-
函数对比指南
| 函数 | 典型应用场景 | 性能特性 | 注意事项 |
|---------------|-----------------------------|--------------|----------------------|
|key_comp()
| 自定义排序规则、比较算法设计| 获取即用 | 与容器排序规则一致 |
|value_comp()
| 泛型编程中统一处理容器元素 | 同key_comp
| 仅语义差异,功能相同 |
|swap()
| 高效转移大数据集所有权 | 常数时间 | 不影响迭代器有效性 |
推荐优先使用
swap()
替代手动复制,尤其在处理大型数据集时能显著提升性能。
7. set
与 multiset
关键差异
-
核心差异总览
| 特性 |set
|multiset
|
|--------------|------------------------------|--------------|
| 元素唯一性 | ✅ 唯一 | ❌ 可重复 |
| 底层结构 | 红黑树(自动排序) | 相同 |
| 主要函数差异 | 插入返回值、删除/计数行为不同 | 允许重复操作 | -
构造函数与容量函数
| 函数/操作 |set
行为 |multiset
行为 | 差异说明 |
|-----------|------------------|--------------------------|---------------|
| 默认构造 |set<T> s;
|multiset<T> ms;
| 无差异 |
|size()
| 返回唯一元素数量 | 返回所有元素数量(含重复)| 结果可能不同 | -
插入函数
| 函数签名 |set
返回值/行为 |multiset
返回值/行为| 差异说明 |
|---------------------------|-----------------------|-----------------------|-----------------------|
|insert(const T& value)
|pair<iterator, bool>
|iterator
|set
返回是否插入成功|
|emplace(Args&&... args)
| 同insert
| 同insert
| 返回值差异相同 |
| 插入重复元素 | 自动忽略 | 允许插入 | 行为不同 |示例:
set<int> s = {1, 2, 3}; auto [iter, success] = s.insert(2); // success = false multiset<int> ms = {1, 2, 2}; auto iter = ms.insert(2); // 成功插入第三个 2
-
删除函数
| 函数签名 |set
返回值/行为 |multiset
返回值/行为 | 差异说明 |
|-----------------------|-------------------|------------------------|------------------------|
|erase(const T& key)
| 返回0
或1
| 返回实际删除的数量(≥0)|multiset
可能删除多个|
|erase(iterator pos)
| 删除单个元素 | 同set
| 无差异 |示例:
multiset<int> ms = {2, 2, 3}; ms.erase(2); // 删除所有 2,返回 2
-
查找与计数函数
| 函数签名 |set
返回值/行为 |multiset
返回值/行为 | 差异说明 |
|-----------------------|--------------------|---------------------------|------------------------ |
|count(const T& key)
| 返回0
或1
| 返回实际匹配数量(可能 ≥1)|multiset
支持重复计数 |
|equal_range(key)
| 范围最多含 1 个元素| 范围可能含多个连续元素 | 用途不同 |示例:
multiset<int> ms = {5, 5, 5}; auto [first, last] = ms.equal_range(5); // first→5, last→end
-
其他函数与行为
| 函数/操作 |set
行为 |multiset
行为 | 差异说明 |
|----------------|-------------------------|---------------------------|------------------------|
|find(key)
| 返回首个匹配元素的迭代器| 同set
| 无差异(但结果可能不同) |
| 迭代器遍历 | 按升序访问唯一元素 | 按升序访问所有元素(含重复)| 输出内容不同 |
8. 关键特性
- 底层结构:红黑树(自动平衡二叉搜索树),元素自动排序(默认升序)
- 元素唯一性:
set
:元素唯一(重复插入被忽略)multiset
:允许重复元素
- 修改限制:元素不可直接修改(需删除后重新插入)
- 时间复杂度:
- 查找/插入/删除:平均 O(log n)
- 迭代器步进:O(1)
9. 完整示例
#include <set>
#include <vector>int main() {// ========== 1. 构造函数 ==========// 1.1 默认构造std::multiset<int> ms1; // 创建空 multiset // 1.2 自定义比较器(降序排列)auto comp = [](int a, int b) { return a > b; };std::multiset<int, decltype(comp)> ms2(comp); // 创建空容器,元素按降序排列 // 1.3 迭代器范围构造 std::vector<int> vec = {5, 2, 2, 8};std::multiset<int> ms3(vec.begin(), vec.end()); // ms3 = {2, 2, 5, 8}// 1.4 初始化列表构造 std::multiset<std::string> ms4 = {"apple", "banana", "apple"}; // 含重复元素"apple"// ========== 2. 容量操作 ==========// 2.1 检查是否为空if (ms1.empty()) std::cout << "ms1 is empty\n"; // 输出:ms1 is empty// 2.2 获取元素数量 std::cout << "ms3 size: " << ms3.size() << std::endl; // 输出:4(含重复元素计数)// 2.3 获取最大可能元素数 std::cout << "Max size: " << ms4.max_size() << std::endl; // 输出系统支持的最大容量 // ========== 3. 插入操作 ==========// 3.1 插入单个元素 ms1.insert(10); // ms1 = {10}// 3.2 带位置提示的插入(优化效率)auto hint = ms3.find(5); ms3.insert(hint, 3); // 在5附近插入3 → {2, 2, 3, 5, 8}// 3.3 插入范围 int arr[] = {1, 1, 4};ms1.insert(arr, arr + 3); // ms1 = {1, 1, 4, 10}// 3.4 原位构造(避免拷贝)ms4.emplace("cherry"); // 直接构造并插入"cherry" {apple apple banana cherry}// ========== 4. 删除操作 ==========// 4.1 删除指定键的所有元素std::multiset<int> ms5 = {3, 3, 5, 7};ms5.erase(3); // 删除所有3 → {5, 7},返回删除数量2 // 4.2 删除迭代器指向的元素 auto it = ms4.find("apple"); if (it != ms4.end()) ms4.erase(it); // 删除第一个"apple" //{apple banana cherry}// 4.3 删除元素范围auto first = ms3.lower_bound(2); auto last = ms3.upper_bound(3); ms3.erase(first, last); // 删除[2, 3)区间 → {5, 8}// 4.4 清空容器 ms2.clear(); // 移除所有元素 // ========== 5. 查找操作 ==========// 5.1 查找元素 std::multiset<std::string> ms6 = {"cat", "dog", "dog"};auto pos = ms6.find("dog"); // 返回第一个"dog"的迭代器 // 5.2 计数元素出现次数std::cout << "dog count: " << ms6.count("dog") << std::endl; // 输出:2 // // 5.3 检查元素是否存在 (C++20)// if (ms6.contains("cat")) std::cout << "Found cat!\n"; // 输出:Found cat!// 5.4 获取元素范围边界 std::multiset<int> ms7 = {10, 20, 20, 30};auto low = ms7.lower_bound(20); // 首个≥20的元素(第一个20)auto upp = ms7.upper_bound(20); // 首个>20的元素(30)// 5.5 获取相等元素范围 auto [first_eq, last_eq] = ms7.equal_range(20); // [第一个20, 30)// ========== 6. 迭代器操作 ==========// 6.1 顺序遍历for (auto it = ms7.begin(); it != ms7.end(); ++it)std::cout << *it << " "; // 输出:10 20 20 30 // 6.2 逆序遍历 for (auto rit = ms7.rbegin(); rit != ms7.rend(); ++rit)std::cout << *rit << " "; // 输出:30 20 20 10 // ========== 7. 比较器操作 ==========// 7.1 获取键比较器auto key_cmp = ms7.key_comp(); std::cout << "20 < 30? " << key_cmp(20, 30) << std::endl; // 输出:1(true)// 7.2 获取值比较器(等同键比较器)auto val_cmp = ms7.value_comp(); std::cout << "20 < 30? " << val_cmp(*ms7.begin(), 30) << std::endl; // 输出:1return 0;
}