C++中unordered_multiset容器用法示例详解
更新时间:2026年02月10日 08:30:58 作者:你的冰西瓜
这篇文章主要介绍了C++中unordered_multiset容器用法的相关资料,unordered_multiset是以key为元素无序的关联容器,搜索、移除和插入操作是平均常数的时间复杂度,文中通过代码介绍的非常详细,需要的朋友可以参考下
1.unordered_multiset概述
unordered_multiset是C++11引入的关联容器,基于哈希表实现,允许存储重复元素,提供快速的查找、插入和删除操作,平均时间复杂度为O(1)O(1)O(1)。
2. 基本特性
- 哈希表实现:使用哈希函数组织元素
- 允许重复元素:容器中可以包含多个相同值
- 无序存储:元素不以任何特定顺序存储
- 快速访问:平均情况下提供常数时间复杂度的查找
- 动态大小:可以根据需要自动扩展
3. 头文件与声明
#include <unordered_set>
using namespace std;
unordered_multiset<int> ums1; // 空unordered_multiset
unordered_multiset<string> ums2 = {"a", "b", "a"}; // 初始化列表(允许重复)
unordered_multiset<double> ums3(10); // 初始桶数为10
4. 构造函数与初始化
4.1 默认构造
unordered_multiset<int> numbers;
4.2 范围构造
int arr[] = {1, 2, 2, 3, 3, 3};
unordered_multiset<int> nums(arr, arr+6);
4.3 拷贝构造
unordered_multiset<int> ums2(ums1);
4.4 自定义哈希函数和相等比较
struct CaseInsensitiveHash {
size_t operator()(const string& s) const {
size_t h = 0;
for(char c : s) {
h += tolower(c);
}
return h;
}
};
struct CaseInsensitiveEqual {
bool operator()(const string& a, const string& b) const {
if(a.length() != b.length()) return false;
for(size_t i = 0; i < a.length(); ++i) {
if(tolower(a[i]) != tolower(b[i])) return false;
}
return true;
}
};
unordered_multiset<string, CaseInsensitiveHash, CaseInsensitiveEqual> case_insensitive_ms;
5. 容量操作
5.1size()
cout << ums.size(); // 返回元素总数量(包括重复)
5.2empty()
if(ums.empty()) {
cout << "unordered_multiset is empty";
}
5.3max_size()
cout << ums.max_size(); // 返回可容纳的最大元素数
6. 元素访问
6.1 迭代器访问
for(auto it = ums.begin(); it != ums.end(); ++it) {
cout << *it << " ";
}
7. 修改操作
7.1insert()
ums.insert(10); // 插入单个元素
ums.insert({5, 5, 15}); // 插入初始化列表(允许重复)
ums.insert(arr, arr+3); // 插入范围
auto it = ums.insert(20); // 返回指向插入元素的迭代器
7.2emplace()
auto it = ums.emplace(30); // 原地构造元素
7.3erase()
ums.erase(5); // 删除所有值为5的元素
auto it = ums.find(10);
if(it != ums.end()) {
ums.erase(it); // 只删除一个10
}
ums.erase(ums.begin(), ums.end()); // 删除范围
7.4clear()
ums.clear(); // 清空所有元素
7.5swap()
unordered_multiset<int> ums2; ums.swap(ums2); // 交换两个unordered_multiset
8. 查找操作
8.1find()
auto it = ums.find(10); // 返回指向第一个10的迭代器
if(it != ums.end()) {
cout << "Found: " << *it;
}
8.2count()
cout << ums.count(5); // 返回元素5的数量
8.3equal_range()
auto range = ums.equal_range(15); // 返回等于15的元素范围[pair]
for(auto it = range.first; it != range.second; ++it) {
cout << *it << " ";
}
9. 桶操作
9.1bucket_count()
cout << ums.bucket_count(); // 返回桶的数量
9.2max_bucket_count()
cout << ums.max_bucket_count(); // 返回最大桶数
9.3bucket_size()
cout << ums.bucket_size(2); // 返回第2个桶中的元素数
9.4bucket()
cout << ums.bucket("apple"); // 返回"apple"所在的桶索引
10. 哈希策略
10.1load_factor()
cout << ums.load_factor(); // 返回负载因子(元素数/桶数)
10.2max_load_factor()
cout << ums.max_load_factor(); // 返回最大负载因子 ums.max_load_factor(0.75); // 设置最大负载因子
10.3rehash()
ums.rehash(20); // 设置桶数为至少20
10.4reserve()
ums.reserve(100); // 预留空间至少容纳100个元素
11. 完整示例
#include <iostream>
#include <unordered_set>
#include <string>
using namespace std;
int main() {
// 创建并初始化unordered_multiset
unordered_multiset<string> words = {"apple", "banana", "apple", "orange", "banana"};
// 插入元素
words.insert("grape");
words.emplace("pear");
words.insert({"apple", "kiwi", "kiwi"});
// 查找元素
cout << "Number of 'apple': " << words.count("apple") << endl;
auto found = words.find("orange");
if(found != words.end()) {
cout << "Found orange at bucket #" << words.bucket(*found) << endl;
}
// 遍历unordered_multiset
cout << "All words: ";
for(const auto& word : words) {
cout << word << " ";
}
cout << endl;
// 使用equal_range处理重复元素
cout << "All apples: ";
auto range = words.equal_range("apple");
for(auto it = range.first; it != range.second; ++it) {
cout << *it << " ";
}
cout << endl;
// 删除元素
words.erase("banana"); // 删除所有banana
auto it = words.find("kiwi");
if(it != words.end()) {
words.erase(it); // 只删除一个kiwi
}
// 桶信息
cout << "\nBucket information:" << endl;
cout << "Number of buckets: " << words.bucket_count() << endl;
cout << "Current load factor: " << words.load_factor() << endl;
// 调整哈希表
words.rehash(15);
cout << "After rehash, bucket count: " << words.bucket_count() << endl;
// 容量信息
cout << "\nSize: " << words.size() << endl;
cout << "Is empty: " << (words.empty() ? "Yes" : "No") << endl;
return 0;
}
12. 性能提示
- 平均情况下查找、插入、删除时间复杂度为O(1)O(1)O(1)
- 最坏情况下(哈希冲突严重)时间复杂度退化为O(n)O(n)O(n)
- 负载因子过高会影响性能,可适时
rehash() - 自定义类型需要提供哈希函数和相等比较
- 迭代器在插入操作后可能失效(重新哈希时)
13. 与multiset比较
| 特性 | unordered_multiset | multiset |
|---|---|---|
| 实现方式 | 哈希表 | 红黑树 |
| 元素顺序 | 无序 | 自动排序 |
| 查找复杂度 | 平均O(1)O(1)O(1) | O(log2n)O(\log_2 n)O(log2n) |
| 内存使用 | 通常较少 | 通常较多 |
| 迭代器稳定性 | 插入可能失效 | 稳定(除删除元素) |
14. 与unordered_set比较
| 特性 | unordered_multiset | unordered_set |
|---|---|---|
| 元素唯一性 | 允许重复 | 不允许重复 |
count()返回值 | 可能大于111 | 000或111 |
equal_range() | 常用于处理重复 | 较少使用 |
总结
到此这篇关于C++中unordered_multiset容器用法详解的文章就介绍到这了,更多相关C++中unordered_multiset容器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
C++中malloc与free、new与delete的详解与应用
今天小编就为大家分享一篇关于C++中malloc与free、new与delete的详解与应用,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧2018-12-12


最新评论