在C++标准模板库STL中,set和multiset都是关联式容器,底层通常基于红黑树实现,能够自动对元素排序。两者最核心的区别在于是否允许容器中存在重复的键值。理解这一点,对实际开发中的数据结构选型非常关键。

一、基本概念区别
set是一种有序集合,里面的元素唯一,不能重复。如果尝试插入一个已经存在的元素,插入操作不会生效。multiset同样是有序集合,但允许出现多个相等的元素,插入时不会去重。
1. 头文件与定义
两者都定义在头文件<set>中,模板参数基本一致:
#include <set> using namespace std; set<int> s; // 不允许重复 multiset<int> ms; // 允许重复
2. 插入重复元素的表现
下面代码展示了插入相同元素时的不同结果:
#include <iostream>
#include <set>
using namespace std;
int main() {
set<int> s;
multiset<int> ms;
s.insert(10);
s.insert(10); // 被忽略,set中仍只有一个10
ms.insert(10);
ms.insert(10); // 允许,multiset中有两个10
cout << "set size: " << s.size() << endl; // 输出 1
cout << "multiset size: " << ms.size() << endl; // 输出 2
return 0;
}
二、常用接口的行为差异
虽然查找和遍历接口类似,但在统计个数与删除元素时,两者行为明显不同。
1. count函数的差异
set的count返回值只能是0或1,而multiset的count会返回该元素实际出现的次数。
// 假设 ms 中已有三个 5 int n = ms.count(5); // n 等于 3
2. erase函数的差异
传入具体值时,set的erase会删除那一个唯一元素;multiset的erase会删除所有等于该值的元素。如果只想删一个,要使用迭代器版本。
ms.erase(5); // 删除所有值为5的元素
auto it = ms.find(5);
if (it != ms.end()) {
ms.erase(it); // 只删除一个值为5的元素
}
三、适用场景对比
| 容器 | 是否允许重复 | 典型场景 |
|---|---|---|
| set | 否 | 需要自动去重的排行榜、单词表 |
| multiset | 是 | 统计频数、允许并列的优先队列 |
四、小结
set和multiset接口高度一致,区别集中在重复元素策略上。写代码时应根据业务是否需要保留重复项来选择;使用multiset的erase传值删除时,要小心一次性清掉全部重复值。掌握这些细节,才能更安全高效地运用STL有序容器。