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
相关推荐
leo__5202 小时前
基于C#实现软件注册码注册机制
开发语言·c#·哈希算法
满栀5852 小时前
插件轮播图制作
开发语言·前端·javascript·jquery
Benny_Tang2 小时前
题解:P14841 [THUPC 2026 初赛] 哈姆星与古地球学术行为影响星球文明的考古学分析
c++·算法
不会c嘎嘎2 小时前
QT中的事件机制
开发语言·qt
a努力。2 小时前
阿里Java面试被问:WebSocket的心跳检测和自动重连实现
java·开发语言·python·websocket·面试·职场和发展·哈希算法
行秋2 小时前
MATLAB 中的两大电力仿真库:Simscape Electrical(蓝色库) vs SimPowerSystems(黑色库)
开发语言·matlab
涛起云永2 小时前
Qt 源码编译 -- obj文件无法找到
开发语言·qt
迷途之人不知返2 小时前
C++初识(3)
c++
hzb666662 小时前
xd_day28js原生开发-day31 day41asp.net
开发语言·前端·javascript·安全·web安全