今天我们来详细讲解一下 C++ 中的 std::map<int, int>

一、map是什么

map<int, int> 是 C++ 标准模板库(STL)中的一个关联容器。你可以把它想象成一个特殊的数组,但这个数组的“下标”(我们称之为 ,Key)不一定是连续的整数,可以是任何类型(在这里我们指定为 int),并且它会根据键的值自动进行排序。

  • 第一个 int:表示键(Key)的数据类型。就像数组的索引,用来查找数据。

  • 第二个 int:表示值(Value)的数据类型。就是通过键关联到的实际数据。

  • map容器的特点:容器中的元素总是按照键(Key)从小到大自动排序的。

每个元素都是一个 std::pair<const int, int> 对象,它包含两个部分:

  • first: 键(Key),是 const 类型,意味着一旦插入就不能修改。

  • second: 值(Value),可以修改。

其中每个Key都有一个Value,Value默认为0。Key就好像是一个独一无二的人,是不可变的,而Value是这个人的资产,是可以改变的。

二、map的优势(与普通数组的区别)

假设你有一个普通数组 int arr[10],你只能用 0 到 9 这样的连续整数作为索引。但如果你需要用学生的学号(比如 20240001)作为索引来查找成绩,或者用单词作为索引来查找它的解释,或者用非连续、甚至是非数字的键来查找数据。

这时普通数组就无能为力了,而 std::map 就派上了用场。对于 map<int, int>,虽然键也是 int,但它可以是任意整数,并且顺序是排好的。也可以用map<string, int>,通过字符串来找到该字符串对应的Value,并且顺序也是拍好了的(通过字典序)

三、基本用法

使用map需要包含头文件#include <map>,当然也可以用万能头#include <bits/stdc++.h>

1.创建(声明)一个 map

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

int main() {
    map<int, int> mp; // 创建一个键和值都是int类型的空map
}

2.插入数据

我这里只推荐使用[  ]运算符

mp[8] = 750; // 如果键8不存在,会创建它并赋值750。如果已存在,则会修改它的值。
mp[4];       // 如果键4没有设置Value,那么默认初始为0

3.访问和遍历数据

1.使用[  ]运算符访问

cout << "The value for key 8 is: " << mp[8] << endl; // 输出 750

2.遍历(迭代)map(元素会自动按键排序)

cout << "Iterating through the map:" << endl;

//begin是map的首位,end是map的最后一位的后一位
for (auto it = mp.begin(); it != mp.end(); ++it) {

    // it->first 是键, it->second 是值
    cout << "Key: " << it->first << ", Value: " << it->second << endl;
}

输出

Key: 1, Value: 200
Key: 2, Value: 50
Key: 3, Value: 100
Key: 4, Value: 300
Key: 5, Value: 600
Key: 8, Value: 750

你会发现输出顺序是 1, 2, 3, 4, 5, 8,而不是你插入的顺序。这就是自动排序的特性。

3.范围 for 循环

for (const auto &pair : mp)    // 使用引用避免拷贝
{  
    cout << "Key: " << pair.first << ", Value: " << pair.second << endl;
}

或者

for (const auto &[x,y] : mp)
{  
    cout << "Key: " << x << ", Value: " << y << endl;
}

4.查找元素

建议使用 find() 函数,它比直接用 [] 访问更安全,因为它不会创建新元素。

int key_to_find = 5;
auto it = mp.find(key_to_find);   // 查找键为5的元素

if (it != mp.end()) {
    // 找到了
    cout << "Found! Value is: " << it->second << endl;
} else {
    cout << "Key " << key_to_find << " not found in the map." << endl;
}

5.删除元素

mp.erase(3);    // 删除键为3的元素

//还可以通过迭代器删除
auto it = mp.find(2);
if (it != mp.end()) {
    myMap.erase(it);
}

6.检查是否为空和获取大小

if (mp.empty()) {
    cout << "The map is empty." << endl;
} else {
    cout << "The map has " << mp.size() << " elements." << endl;
}

四、注意事项和常见用途

1.注意事项

  • 排序std::map 基于红黑树实现,元素总是有序的。如果你不需要排序,但需要键值对,可以考虑 std::unordered_map(基于哈希表,平均访问速度更快,但元素无序)。

  • [] 运算符的副作用:如之前所说,myMap[some_key] 如果找不到 some_key,会创建一个新元素。如果你只是想检查一个键是否存在,应该使用 find() 方法。

  • 键的唯一性std::map 中每个键只能出现一次。如果你插入一个已存在的键,新的值会覆盖旧的值(使用 insert 方法插入已存在的键不会覆盖,插入会失败。但使用 [] 赋值会覆盖)。如果需要重复的键,可以使用 std::multimap

2.常见用途

计数器(例题-找到最多的数

vector<int> numbers = {1, 2, 2, 3, 3, 3, 4};
map<int, int> countMap;

for (int num : numbers) {
    countMap[num]++;    //妙用:如果num不存在,会创建并初始化为0,然后++变为1。
}
//现在 countMap[1]==1, countMap[2]==2, countMap[3]==3, countMap[4]==1

建立映射关系:如学号映射到成绩,产品ID映射到价格等。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐