C++中的map容器详解

C++中的map容器详解

1. map概述

map是C++ STL中的关联容器,它存储**键值对(key-value)**并按key自动排序。map基于红黑树实现,提供高效的查找、插入和删除操作。

2. 基本特性

  • 唯一键值:每个key只能出现一次
  • 自动排序:元素总是按key排序
  • 高效查找 :基于key的查找时间复杂度为O(log⁡2n)O(\log_2 n)O(log2n)
  • 键不可修改 :key是const的,value可以修改

3. 头文件与声明

cpp 复制代码
#include <map>
using namespace std;

map<int, string> m1;                     // 空map,key为int,value为string
map<string, int, greater<string>> m2;    // 空map,按key降序排列
map<string, int> m3 = {{"Alice", 25}, {"Bob", 30}};  // 初始化列表

4. 构造函数与初始化

4.1 默认构造

cpp 复制代码
map<string, double> m;  // 创建空map

4.2 范围构造

cpp 复制代码
pair<string, int> arr[] = {{"A", 1}, {"B", 2}};
map<string, int> m(arr, arr+2);  // 用数组范围构造

4.3 拷贝构造

cpp 复制代码
map<string, int> m2(m1);  // 拷贝构造

5. 容量操作

5.1 size()

cpp 复制代码
cout << m.size();  // 返回元素数量

5.2 empty()

cpp 复制代码
if(m.empty()) {
    cout << "Map is empty";
}

5.3 max_size()

cpp 复制代码
cout << m.max_size();  // 返回map可容纳的最大元素数

6. 元素访问

6.1 operator[]

cpp 复制代码
m["Alice"] = 25;      // 插入或修改元素
int age = m["Bob"];   // 访问元素(如果不存在会插入默认值)

6.2 at()

cpp 复制代码
int age = m.at("Alice");  // 访问元素(如果不存在抛出out_of_range异常)

7. 修改操作

7.1 insert()

cpp 复制代码
m.insert({"Charlie", 28});               // 插入单个元素
m.insert(make_pair("David", 32));        // 使用make_pair
m.insert({{"Eve", 27}, {"Frank", 40}});  // 插入多个元素

7.2 emplace()

cpp 复制代码
m.emplace("Grace", 35);  // 原地构造元素,比insert更高效

7.3 erase()

cpp 复制代码
m.erase("Alice");                   // 删除指定key的元素
m.erase(m.begin());                 // 删除迭代器指向的元素
m.erase(m.begin(), m.find("Bob"));  // 删除范围元素

7.4 clear()

cpp 复制代码
m.clear();  // 清空所有元素

7.5 swap()

cpp 复制代码
map<string, int> m2;
m.swap(m2);  // 交换两个map的内容

8. 查找操作

8.1 find()

cpp 复制代码
auto it = m.find("Alice");  // 查找元素,返回迭代器
if(it != m.end()) {
    cout << "Found: " << it->first << " => " << it->second;
}

8.2 count()

cpp 复制代码
if(m.count("Bob")) {  // 返回匹配key的数量(0或1)
    cout << "Key exists";
}

8.3 lower_bound() & upper_bound()

cpp 复制代码
auto lb = m.lower_bound("B");  // 返回第一个不小于"B"的元素的迭代器
auto ub = m.upper_bound("D");  // 返回第一个大于"D"的元素的迭代器

8.4 equal_range()

cpp 复制代码
auto range = m.equal_range("C");  // 返回等于"C"的元素范围
// range.first是lower_bound, range.second是upper_bound

9. 迭代器

9.1 begin() & end()

cpp 复制代码
for(auto it = m.begin(); it != m.end(); ++it) {
    cout << it->first << ": " << it->second << endl;
}

9.2 rbegin() & rend()

cpp 复制代码
for(auto rit = m.rbegin(); rit != m.rend(); ++rit) {
    cout << rit->first << ": " << rit->second << endl;  // 反向遍历
}

10. 完整示例

cpp 复制代码
#include <iostream>
#include <map>
#include <string>
using namespace std;

int main() {
    // 创建并初始化map
    map<string, int> ageMap = {{"Alice", 25}, {"Bob", 30}};
    
    // 插入元素
    ageMap.insert({"Charlie", 28});
    ageMap.emplace("David", 32);
    ageMap["Eve"] = 27;  // 使用operator[]插入
    
    // 修改元素
    ageMap["Alice"] = 26;  // 修改Alice的年龄
    
    // 查找元素
    if(ageMap.find("Bob") != ageMap.end()) {
        cout << "Bob's age: " << ageMap["Bob"] << endl;
    }
    
    // 删除元素
    ageMap.erase("Charlie");
    
    // 遍历map
    cout << "All entries:" << endl;
    for(const auto& [name, age] : ageMap) {  // C++17结构化绑定
        cout << name << ": " << age << endl;
    }
    
    // 范围查询
    cout << "Names between A and C:" << endl;
    auto low = ageMap.lower_bound("A");
    auto up = ageMap.upper_bound("C");
    for(auto it = low; it != up; ++it) {
        cout << it->first << ": " << it->second << endl;
    }
    
    // 容量信息
    cout << "Size: " << ageMap.size() << endl;
    cout << "Is empty: " << (ageMap.empty() ? "Yes" : "No") << endl;
    
    return 0;
}

11. 自定义比较函数

cpp 复制代码
struct CaseInsensitiveCompare {
    bool operator()(const string& a, const string& b) const {
        return strcasecmp(a.c_str(), b.c_str()) < 0;
    }
};

map<string, int, CaseInsensitiveCompare> caseInsensitiveMap;

12. 性能提示

  1. 查找操作优先使用find()而非operator[],避免意外插入
  2. 插入大量数据时,考虑预先构造vector再转为map
  3. 使用emplace()替代insert()可避免不必要的拷贝
  4. 对于频繁查找但不需排序的场景,考虑使用unordered_map
相关推荐
赵侃侃爱分享15 小时前
学完Python第一次写程序写了这个简单的计算器
开发语言·python
yolo_guo15 小时前
glog单行 30000 字节限制问题
c++
断眉的派大星15 小时前
# Python 魔术方法(魔法方法)超详细讲解
开发语言·python
2501_9333295515 小时前
技术深度拆解:Infoseek舆情处置系统的全链路架构与核心实现
开发语言·人工智能·自然语言处理·架构
妮妮喔妮15 小时前
supabase的webhook报错
开发语言·前端·javascript
我的xiaodoujiao15 小时前
API 接口自动化测试详细图文教程学习系列11--Requests模块3--测试练习
开发语言·python·学习·测试工具·pytest
cccccc语言我来了15 小时前
C++轻量级消息队列服务器
java·服务器·c++
闻缺陷则喜何志丹16 小时前
【背包 组合】P7552 [COCI 2020/2021 #6] Anagramistica|普及+
c++·算法·背包·洛谷·组合
xiaoye-duck16 小时前
【C++:C++11】C++11新特性深度解析:从类新功能、Lambda表达式到包装器实战
开发语言·c++·c++11
qq_120840937116 小时前
Three.js 大场景分块加载实战:从全量渲染到可视集调度
开发语言·javascript·数码相机