文章

map

std::map 是 C++ STL 中的关联容器,存储键值对,键唯一且按顺序排列。底层使用红黑树实现,提供 O(logN) 时间复杂度的插入、删除和查找操作。常用于需要有序数据的场景。

map

map

std::map 是一个关联容器,以 键值对(key-value) 形式存储数据,具有以下特性:

  • 键是唯一的(key 不可重复)
  • 元素按 key 自动排序(默认升序)
  • 插入、删除、查找等操作的时间复杂度为 O(logN)

底层实现

  • std::map 底层基于红黑树(Red-Black Tree)实现
    • 红黑树是一种自平衡的二叉搜索树,插入/删除时通过旋转和变色保持树的平衡
    • 保证最坏情况下的操作(查找、插入、删除)为 O(logN)
  • 所以:std::map 的 key 是有序的,不能随机访问

常用接口

定义方式

1
2
#include <map>
std::map<int, std::string> m;  // key: int, value: string

插入元素

1
2
3
m.insert({1, "apple"}); // 若 key 已经存在,插入操作将失败
m[2] = "banana"; // 如果 key 不存在则插入,存在则修改
m.emplace(3, "orange"); // 更高效的插入

查找元素

1
2
3
if (m.find(2) != m.end()) {
    std::cout << m[2] << std::endl;
}

遍历 map

1
2
3
for (auto& [key, value] : m) {
    std::cout << key << " => " << value << std::endl;
}

删除元素

1
m.erase(2); // 删除 key 为 2 的元素

常用接口汇总

方法说明
insert({k, v})插入键值对
emplace(k, v)就地构造键值对(更快)
operator[]访问或插入元素
at(k)访问元素(若无则抛异常)
find(k)查找 key,返回迭代器
erase(k)删除 key 对应元素
clear()清空 map
size()元素个数
count(k)是否存在该 key(返回 0 或 1)
begin()/end()迭代器

使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <map>
using namespace std;

int main() {
    map<string, int> wordCount;
    string words[] = {"apple", "banana", "apple", "orange", "banana", "apple"};

    for (const auto& word : words) {
        wordCount[word]++;
    }

    for (auto& [word, count] : wordCount) {
        cout << word << ": " << count << endl;
    }

    return 0;
}

输出:

1
2
3
apple: 3
banana: 2
orange: 1

常见问题

mapunordered_map 的区别?

对比项mapunordered_map
底层结构红黑树哈希表
元素顺序有序(按 key 排序)无序
查找效率O(logN)O(1)(最优),最坏 O(N)
内存占用较少较多
使用场景需要有序遍历性能优先,快速查找

如何自定义 key 类型?

1
2
3
4
5
6
7
8
struct Point {
    int x, y;
    bool operator<(const Point& other) const {
        return tie(x, y) < tie(other.x, other.y);
    }
};

map<Point, string> pointMap;

map 的 key 类型必须能进行 < 比较,用于排序。

map 的 insert 和 operator[] 有什么区别?

方法特性
m.insert({k, v})如果 key 已存在,不会修改 value
m[k] = v如果 key 不存在,插入新值;否则会修改 value
m.at(k)若 key 不存在会抛出异常

如何按 value 排序?

map 默认只能按 key 排序,若要按 value 排序,可将 map 转为 vector,再排序:

1
2
3
4
vector<pair<string, int>> vec(m.begin(), m.end());
sort(vec.begin(), vec.end(), [](auto& a, auto& b){
    return a.second > b.second; // 降序
});

map 支持重复 key 吗?

  • 不支持,key 唯一。
  • 如果需要支持重复 key,用 std::multimap

拓展建议

  • 使用 map 时注意不要误用 m[k] 来查找是否存在,m[k] 会插入默认值
  • 若无序 + 高性能需求,建议用 unordered_map
  • 遇到性能瓶颈时,可考虑 flat_mapsparse_map(第三方库)
本文由作者按照 CC BY 4.0 进行授权