一、简要概念
multiset是C++标准模板库(STL)中的一种关联式容器,用于存储可重复的唯一键值对元素。特性如下:
元素可重复:允许多个相同键值对的元素共存
底层实现:基于红黑树(一种平衡二叉树),支持高效查找、插入和删除操作
排序规则:元素按键值自动排序,默认使用<运算符,可通过自定义仿函数调整排序逻辑
两者的区别:
set不允许重复元素,即每个元素只能出现一次
multiset允许容器中有重复元素
两者共同点:
都是关联容器,基于红黑树实现,因此插入、删除和查找的时间复杂度都是O(log n)
元素都是自动排序的
使用时包含头文件 , #include<set>
二、基本定义
multiset<键类型,值类型,比较器> 变量名 默认比较器是升序
当比较器写为:greater<类型> 时, 为降序
例如:
// 定义一个存储 int 的 multiset,默认按 less 升序排列
multiset ms1;
// 定义一个降序排列的 multiset
multiset> ms2;
// 使用初始化列表初始化
multiset ms3 = {5, 2, 8, 2, 9, 2, 5};
一些简单的容器方法如:
clear()清空容器, empty()判空
begin() 返回首个元素的迭代器, end() 返回最后以一个元素的下一个位置的迭代器
三、常用方法以及使用
1. 基于迭代器的遍历
// 使用迭代器
for (multiset::iterator it = ms1.begin(); it != ms1.end(); ++it)
{
cout << *it << " ";
}
2. 基于范围for循环(C++11)
//范围for循环 (C++11)
for (const auto& elem : ms)
{
cout << elem << " ";
}
3. 插入元素insert
时间复杂度为 O(log n)
#include
#include
using namespace std;
int main
{
multiset ms;
ms.insert(10);
ms.insert(20);
ms.insert(10); // 允许插入重复值
ms.insert(5);
// 此时 ms 的内容: 5, 10, 10, 20
//范围for循环 (C++11)
for (const auto& elem : ms)
{
cout << elem << " ";
}
return 0;
}
4. 查找元素find(key)
#include
#include
using namespace std;
int main
{
multiset ms;
ms.insert(10);
ms.insert(20);
ms.insert(10); // 允许插入重复值
ms.insert(5);
auto it = ms.find(10);
if (it != ms.end())
{
cout << "Found: " << *it << endl; // 输出: Found: 10
// 注意:这里找到的是第一个 2
}
return 0;
}
5. 统计元素出现次数count(key)
#include
#include
using namespace std;
int main
{
multiset ms;
ms.insert(10);
ms.insert(20);
ms.insert(10); // 允许插入重复值
ms.insert(5);
cout << ms.count(10) << endl; // 输出: 2
cout << ms.count(5) << endl; // 输出: 1
return 0;
}
6. 删除元素erase
erase 有三种重载形式:
6.1 erase(iterator pos): 删除迭代器 pos 指向的元素
#include
#include
using namespace std;
int main
{
multiset ms = {1, 2, 2, 3, 4};
auto it = ms.find(2);
if (it != ms.end())
{
ms.erase(it); // 只删除找到的第一个 2
}
// ms 现在为: 1, 2, 3, 4
//范围for循环 (C++11)
for (const auto& elem : ms)
{
cout << elem << " ";
}
return 0;
}
6.2 erase(const key_type& key): 删除所有值为 key 的元素,返回被删除的元素个数
#include
#include
using namespace std;
int main
{
multiset ms = {1, 2, 2, 3, 4};
size_t num_removed = ms.erase(2); // 删除所有的 2
cout << num_removed << endl; // 输出: 2
// ms 现在为: 1, 3, 4
//范围for循环 (C++11)
for (const auto& elem : ms)
{
cout << elem << " ";
}
return 0;
}
6.3 erase(iterator first, iterator last): 删除 [first, last) 区间内的所有元素。
#include
#include
using namespace std;
int main
{
multiset ms = {1, 2, 3, 4, 5};
// 删除 [2, 4) 区间,即 2 和 3
auto it1 = ms.find(2);
auto it2 = ms.find(4);
ms.erase(it1, it2);
// ms 现在为: 1, 4, 5
//范围for循环 (C++11)
for (const auto& elem : ms)
{
cout << elem << " ";
}
return 0;
}
7. 获取范围:equal_range
对于 multiset,处理重复元素时,equal_range是一个极其有用的函数。
它返回一个pair<iterator, iterator>,其中:
first是指向第一个不小于key的元素的迭代器(即lower_bound)。second是指向第一个大于key的元素的迭代器(即upper_bound)。
这个区间 [first, second)包含了所有等于 key 的元素。
#include
#include
using namespace std;
int main
{
multiset ms = {5, 2, 8, 2, 9, 2};
// 获取所有等于 2 的元素的范围
auto range = ms.equal_range(2);
// 遍历这个范围,打印所有的 2
for (auto it = range.first; it != range.second; ++it)
{
cout << *it << " "; // 输出: 2 2 2
}
cout << endl;
return 0;
}
8. 获取边界:lower_bound和 upper_bound
lower_bound(key): 返回指向第一个不小于key的元素的迭代器。upper_bound(key): 返回指向第一个大于key的元素的迭代器。
#include
#include
using namespace std;
int main
{
multiset ms = {1, 2, 2, 3, 4};
// 找到 [2, 3) 区间
auto low = ms.lower_bound(2); // 指向第一个 2
auto up = ms.upper_bound(2); // 指向 3
for (auto it = low; it != up; ++it)
{
cout << *it << " "; // 输出: 2 2
}
return 0;
}
浙公网安备 33010602011771号