C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > C++中unordered_multiset容器

C++中unordered_multiset容器用法示例详解

作者:你的冰西瓜

这篇文章主要介绍了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. 性能提示

  1. 平均情况下查找、插入、删除时间复杂度为O(1)O(1)O(1)
  2. 最坏情况下(哈希冲突严重)时间复杂度退化为O(n)O(n)O(n)
  3. 负载因子过高会影响性能,可适时rehash()
  4. 自定义类型需要提供哈希函数和相等比较
  5. 迭代器在插入操作后可能失效(重新哈希时)

13. 与multiset比较

特性unordered_multisetmultiset
实现方式哈希表红黑树
元素顺序无序自动排序
查找复杂度平均O(1)O(1)O(1)O(log⁡2n)O(\log_2 n)O(log2n)
内存使用通常较少通常较多
迭代器稳定性插入可能失效稳定(除删除元素)

14. 与unordered_set比较

特性unordered_multisetunordered_set
元素唯一性允许重复不允许重复
count()返回值可能大于111000111
equal_range()常用于处理重复较少使用

总结 

到此这篇关于C++中unordered_multiset容器用法详解的文章就介绍到这了,更多相关C++中unordered_multiset容器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文