C++ 入门第 21 天:STL 容器之无序映射与无序多重映射

往期回顾:

C++ 入门18:STL 容器之栈(stack)与队列(queue)-优快云博客

C++ 入门19:STL 容器之优先队列(priority_queue)-优快云博客

C++ 入门第 20 天:STL 容器之无序集合与无序多重集合-优快云博客


 C++ 入门第 21 天:STL 容器之无序映射与无序多重映射

一、前言

在前一节中,我们学习了无序集合(unordered_set)及其变种。在实际开发中,除了存储单个元素外,我们常常需要存储键值对(key-value)数据。例如,通过一个键快速找到对应的值。在 C++ 中,unordered_mapunordered_multimap 便是专门用于处理无序键值对的容器。

这两个容器基于哈希表实现,能够以平均 O(1)O(1)O(1) 的时间完成插入、删除和查找操作。

1. 无序映射(unordered_map)

unordered_map 是一个 无序关联容器,用于存储唯一键值对(key-value)。它的特点包括:

  1. 底层实现:基于哈希表,效率高。
  2. 键的唯一性:键(key)必须唯一。
  3. 无序存储:键值对的存储顺序与插入顺序无关。

1.1 常用操作

以下是 unordered_map 的常用操作:

成员函数功能说明
insert(pair<key, value>)插入键值对
erase(key)删除指定键对应的键值对
find(key)查找键,返回对应迭代器
operator[]通过键访问值(若不存在会自动插入)
size()获取键值对的数量
empty()检查容器是否为空

示例代码:基本操作

#include <iostream>
#include <unordered_map>
using namespace std;

int main() {
    // 定义一个无序映射
    unordered_map<string, int> umap;

    // 插入键值对
    umap.insert({"Alice", 25});
    umap.insert({"Bob", 30});
    umap["Charlie"] = 20; // 使用[]操作符插入

    // 遍历容器
    cout << "Contents of unordered_map:" << endl;
    for (const auto& pair : umap) {
        cout << pair.first << ": " << pair.second << endl;
    }

    // 查找键
    if (umap.find("Alice") != umap.end()) {
        cout << "Alice's age: " << umap["Alice"] << endl;
    }

    // 删除键
    umap.erase("Bob");
    cout << "After removing Bob:" << endl;
    for (const auto& pair : umap) {
        cout << pair.first << ": " << pair.second << endl;
    }

    return 0;
}

输出结果(顺序可能不同):

Contents of unordered_map:
Charlie: 20
Alice: 25
Bob: 30
Alice's age: 25
After removing Bob:
Charlie: 20
Alice: 25

1.2 注意事项

  1. 自动插入行为:如果通过 [] 访问不存在的键,会自动插入该键,值初始化为默认值(如 int 为 0)。
  2. 哈希冲突处理unordered_map 使用开放地址法或链地址法解决冲突。
  3. 重新哈希(rehash):当装载因子过高时,会重新分配存储桶,导致性能下降。

2. 无序多重映射(unordered_multimap)

unordered_multimapunordered_map 类似,但允许键重复。

2.1 常用操作

成员函数功能说明
insert(pair<key, value>)插入键值对
equal_range(key)返回与某键相关的所有键值对的范围
count(key)返回某键出现的次数

示例代码:无序多重映射

#include <iostream>
#include <unordered_map>
using namespace std;

int main() {
    // 定义一个无序多重映射
    unordered_multimap<string, int> ummap;

    // 插入键值对
    ummap.insert({"Alice", 25});
    ummap.insert({"Bob", 30});
    ummap.insert({"Alice", 35}); // 允许重复键

    // 遍历容器
    cout << "Contents of unordered_multimap:" << endl;
    for (const auto& pair : ummap) {
        cout << pair.first << ": " << pair.second << endl;
    }

    // 查找某键的所有值
    auto range = ummap.equal_range("Alice");
    cout << "Values associated with Alice:" << endl;
    for (auto it = range.first; it != range.second; ++it) {
        cout << it->second << " ";
    }
    cout << endl;

    return 0;
}

输出结果(顺序可能不同):

Contents of unordered_multimap:
Alice: 25
Bob: 30
Alice: 35
Values associated with Alice:
25 35

3. unordered_mapunordered_multimap 的性能分析

优点

  1. 高效操作:基于哈希表,插入、删除和查找操作的平均时间复杂度为 O(1)O(1)O(1)。
  2. 灵活性强:支持键值对存储,方便快速检索和更新数据。

缺点

  1. 无序存储:键值对的顺序与插入顺序无关,适合只关心内容的场景。
  2. 哈希冲突:在哈希函数不理想或装载因子过高时,性能可能下降。
  3. 占用内存多:哈希表存储需要额外的内存开销。

4. 实际应用场景

  • 快速检索:通过键快速找到对应值,例如字典查询。
  • 频率统计:统计某些键的出现次数(可用 unordered_multimap)。
  • 缓存机制:用作缓存容器,通过键值快速检索数据。

示例:统计单词出现次数

题目描述

给定一段文本,统计每个单词出现的次数。

示例代码
#include <iostream>
#include <unordered_map>
#include <sstream>
#include <string>
using namespace std;

int main() {
    string text = "hello world hello C++ world";
    unordered_map<string, int> wordCount;

    // 将字符串分割为单词
    stringstream ss(text);
    string word;
    while (ss >> word) {
        wordCount[word]++;
    }

    // 输出每个单词的出现次数
    cout << "Word frequencies:" << endl;
    for (const auto& pair : wordCount) {
        cout << pair.first << ": " << pair.second << endl;
    }

    return 0;
}

输出结果

Word frequencies:
hello: 2
world: 2
C++: 1

5. unordered_mapmap 的对比 

特性unordered_mapmap
底层结构哈希表红黑树
是否有序无序有序
查找时间复杂度O(1)O(1)O(1)(平均情况)O(log⁡n)O(\log n)O(logn)
插入、删除时间复杂度O(1)O(1)O(1)(平均情况)O(log⁡n)O(\log n)O(logn)

结语

以上就是 C++ 标准模板库中的无序映射与无序多重映射的基础知识点了。这两种容器非常适合需要快速检索键值对数据的场景。理解它们的特性和使用方法,可以显著提升我们的代码效率。

都看到这里了,点个赞再走呗朋友~

加油吧,预祝大家变得更强!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值