C++ STL容器:map 基本用法

C++ STL容器 map 基本用法详解

map 是 C++ 标准模板库(STL)中的关联容器,存储的元素是 键值对(key-value pair),并根据 键(key)自动排序(默认按 key 升序)。map 的键是唯一的,不能重复。

1. 头文件与定义

#include <map>
#include <string>
using namespace std;

// 定义一个空的 map
map<int, string> m1;               // key为int, value为string
map<string, double> priceMap;      // key为string, value为double

2. 插入元素

使用 [] 运算符
最简单直接,如果键不存在则插入,存在则覆盖值。

m1[1] = "apple";
m1[2] = "banana";
m1[3] = "cherry";

使用 insert 函数

  • 插入一个 pair
  • 如果键已存在,插入失败(不会覆盖原有值)
m1.insert(pair<int, string>(4, "date"));
m1.insert(make_pair(5, "elderberry"));
m1.insert({6, "fig"});   // C++11 初始化列表

使用 emplace (C++11,更高效)
直接在容器内构造元素,避免拷贝。

m1.emplace(7, "grape");

3. 访问元素

使用 [] 运算符
如果键不存在,会自动插入一个使用默认值构造的元素。

cout << m1[2] << endl;      // 输出: banana
cout << m1[8] << endl;      // key=8 不存在,自动插入空字符串,输出空

使用 at() 函数(推荐)
带边界检查,若键不存在会抛出 std::out_of_range 异常。

try {
    cout << m1.at(3) << endl;  // 输出: cherry
    cout << m1.at(9) << endl;  // 抛出异常
} catch (const out_of_range& e) {
    cout << "Key not found!" << endl;
}

使用 find 查找
返回迭代器,若未找到返回 end()

auto it = m1.find(2);
if (it != m1.end()) {
    cout << "Found: " << it->second << endl;
} else {
    cout << "Not found" << endl;
}

4. 删除元素

方法说明
erase(key)删除键为 key 的元素,返回删除个数(map中为0或1)
erase(iterator)删除迭代器指向的元素
erase(first, last)删除区间 [first, last) 内的元素
clear()清空整个 map
m1.erase(3);                     // 删除 key=3 的元素
auto it = m1.find(4);
if (it != m1.end()) {
    m1.erase(it);                // 通过迭代器删除
}
m1.clear();                      // 清空

5. 遍历 map

使用迭代器

for (map<int, string>::iterator it = m1.begin(); it != m1.end(); ++it) {
    cout << "Key: " << it->first << ", Value: " << it->second << endl;
}

C++11 范围 for 循环(推荐)

for (const auto& pair : m1) {
    cout << pair.first << " => " << pair.second << endl;
}

C++17 结构化绑定(更清晰)

for (const auto& [key, value] : m1) {
    cout << key << " : " << value << endl;
}

6. 常用成员函数

函数作用
size()返回元素个数
empty()判断是否为空
count(key)返回某个键的出现次数(map中非0即1)
lower_bound(key)返回第一个 key >= 给定键 的迭代器
upper_bound(key)返回第一个 key > 给定键 的迭代器

7. 自定义键的排序规则

默认使用 std::less<Key>(即 < 运算符)升序排列。可以通过指定比较函数或函数对象改变排序方式。

使用 greater 实现降序

map<int, string, greater<int>> descMap;
descMap[1] = "one";
descMap[2] = "two";
// 遍历顺序:2, 1

自定义比较函数(Lambda,C++11)

auto cmp = [](const string& a, const string& b) {
    return a.length() < b.length();   // 按字符串长度升序
};
map<string, int, decltype(cmp)> strMap(cmp);
strMap["apple"] = 5;
strMap["kiwi"]  = 4;
strMap["banana"]= 6;

8.二分查找:lower_bound(key)/upper_bound(key)

两个函数是典型的二分查找接口(返回迭代器,指向第一个 >= key> key 的位置)。

// 查找第一个 key >= 2 的元素
auto it = ma.lower_bound(2);
if (it != ma.end()) {
    cout << "lower_bound(2): " << it->first << " => " << it->second << endl;
}

// 查找第一个 key > 2 的元素
auto it2 = ma.upper_bound(2);
if (it2 != ma.end()) {
    cout << "upper_bound(2): " << it2->first << " => " << it2->second << endl;
}

9.注意事项

map 默认只能通过 key 查找 value,如果想实现“根据 value 查找 key”,也有几种变通办法

  • 直接遍历查找(简单但效率低,时间复杂度 O ( n ) O(n) O(n),适合小规模数据或偶尔查询。
  • 使用反向映射(推荐,查询 O ( 1 ) O(1) O(1) O ( l o g n ) O(log n) O(logn)
  1. 如果经常需要双向查找,可以手动维护一个反向 map。
  2. 假设 value 也是唯一的(否则反向映射无法处理重复值)。
  3. 更新原始 map 时,同步更新反向 map。

10. 完整示例代码

#include <iostream>
#include <map>
#include <string>
using namespace std;

int main() {
    map<string, int> fruitCount;

    // 插入
    fruitCount["apple"] = 10;
    fruitCount["banana"] = 5;
    fruitCount.insert({"orange", 8});
    fruitCount.emplace("grape", 12);

    // 访问与修改
    fruitCount["apple"] += 2;
    cout << "Apple count: " << fruitCount.at("apple") << endl;

    // 查找
    string target = "banana";
    auto it = fruitCount.find(target);
    if (it != fruitCount.end()) {
        cout << target << " found, count = " << it->second << endl;
    }

    // 遍历
    cout << "\nAll fruits:" << endl;
    for (const auto& [name, count] : fruitCount) {
        cout << name << " => " << count << endl;
    }

    // 删除
    fruitCount.erase("orange");

    // 大小
    cout << "\nTotal fruit types: " << fruitCount.size() << endl;

    return 0;
}

11. 小结

特性说明
底层实现红黑树(自平衡二叉搜索树)
元素顺序按键自动排序
查找/插入/删除时间复杂度 O(log n)
键唯一性键不允许重复,重复插入会覆盖或失败
适用场景需要按键排序、快速查找、键唯一关联数据
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值