地图在 C++ 标准模板库 (STL)

Map 是什么 C++?
In C++映射(Map)是一种关联容器,以映射的形式存储数据项。映射中的每个数据项都由一个键值对和一个映射值组成。两个映射值不能具有相同的键值对。
键值用于对元素进行排序和唯一标识,而映射值则存储与每个键关联的内容。两者类型可能不同,但成员类型会将它们组合成一个包含两者的键值对。
在编写任何代码之前,了解为什么地图通常是合适的容器会很有帮助。
为什么要使用 std::map?
以下是使用地图的理由:
- std::map 只存储唯一键,并根据选定的排序标准进行排序。
- 使用密钥搜索元素既简单又快捷。
- 每个键仅附加一个元素。
- std::map 可以用作关联数组。
- std::map 可以使用平衡二叉树实现。
要利用这些优势,首先要了解声明语法。
句法
要声明 std::map,请使用以下语法:
std::map<key_datatype, value_datatype>map_name;
- 此 键数据类型 表示地图键的数据类型。
- 此 值数据类型 表示与映射键对应的值的数据类型。
- 此 地图名称 是地图的名称。
例如:
map<string, int> my_map;
我们声明了一个名为 my_map 的映射。该映射的键数据类型为字符串,值数据类型为整数。
会员类型
成员函数可以使用以下成员类型作为参数或返回类型:
- 密钥类型: 键(模板中的第一个参数)
- 映射类型: T(模板中的第二个参数)
- 键比较: 比较(模板中的第三个参数)
- 分配器类型: 分配(模板中的第四个参数)
- 值类型: 一对
- 值比较: 用于比较元素的嵌套函数类
- 参考: 分配器类型::reference
- const_reference: 分配器类型::const_reference
- 指针: 分配器类型::指针
- const_pointer(常量指针): 分配器类型::const_pointer
- 迭代器(iterator): 指向 value_type 的双向迭代器
- const_iterator(常量迭代器): 指向 const value_type 的双向迭代器
- 反向迭代器(reverse_iterator): 反向迭代器
- const_reverse_iterator(反向迭代器): 常数反向迭代器
- 差异类型: ptrdiff_t
- 尺码类型: 尺寸_t
std::map 的内置函数
std::map 带有内置函数。其中包括:
- 开始 () – 此函数返回指向映射中第一个元素的迭代器。
- 尺寸() – 此函数返回映射中的项目数。
- 空的() – 此函数返回一个布尔值,表示映射是否为空。
- 插入(键值对) – 此函数将一个新的键值对插入到映射中。
- 查找(val) – 如果找到 val 元素,此函数会将迭代器返回给该元素。否则,它返回 m.end()。
- 擦除(迭代器位置) – 此函数删除迭代器指向的位置处的项。
- 擦除(const g) – 此函数从映射中删除键值对 g。
- 明确() 此函数会删除地图中的所有项目。
定义好函数之后,以下示例将把它们付诸实践,首先是迭代。
迭代 Map 元素
您可以遍历地图元素。我们只需要创建一个迭代器并使用它即可。例如:
例子1
#include <iostream> #include <string> #include <map> using namespace std; int main() { map<int, string> Students; Students.insert(std::pair<int, string>(200, "Alice")); Students.insert(std::pair<int, string>(201, "John")); cout << "Map size is: " << Students.size() << endl; cout << endl << "Default map Order is: " << endl; for (map<int, string>::iterator it = Students.begin(); it != Students.end(); ++it) { cout << (*it).first << ": " << (*it).second << endl; } }
输出:
以下是代码截图:
Code 说明:
- 将 iostream 头文件包含到我们的代码中以使用其功能。
- 将字符串头文件包含到我们的代码中以使用其功能。
- 将地图头文件包含到我们的代码中以使用其功能。
- 将 std 命名空间包含到我们的代码中以便使用它的类而无需调用它。
- 调用 main() 函数。{ 标记函数主体的开始。
- 创建一个名为 Students 的映射,其中键是整数,值是字符串。
- 将值插入到映射 Students 中。键 200 和值 Alice 将被插入到映射中。
- 将值插入到映射 Students 中。键 201 和值 John 将被插入到映射中。
- 使用 size() 函数获取名为 Students 的地图的大小。这应该返回 2。
- 在控制台上打印一些文本。
- 使用 for 循环创建一个名为 it 的迭代器,以迭代名为 Students 的映射的元素。
- 在控制台上打印地图学生的值。
- for 循环主体的结束。
- main() 函数体结束。
在 std::map 中插入数据
您可以使用 insert() 函数向 std::map 中添加元素。请记住,std::map 的键必须是唯一的。
因此,它首先检查每个键是否存在于映射中。如果存在,则不会插入该条目,而是返回现有条目的迭代器。如果不存在,则插入该条目。
该函数有以下几种变体:
- 插入(对) – 通过这种变体,将键值对插入到映射中。
- 插入(start_itr, end_itr) – 通过这种变化,条目将插入到另一个映射中由 start_itr 和 end_itr 定义的范围内。
insert_or_assign() 函数的工作方式与 insert() 函数相同,但如果给定的键已存在于映射中,则会修改其值。
例子2
#include <map> #include <iostream> using namespace std; int main() { map<int, int> m{ {1,3} , {2,4} , {3,5} }; m.insert({ 5, 6 }); m.insert({ 1, 8 }); m.insert_or_assign(1, 6); cout << "Key\tElement\n"; for (auto itr = m.begin(); itr != m.end(); ++itr) { cout << itr->first << '\t' << itr->second << '\n'; } return 0; }
输出:
以下是代码截图:
Code 说明:
- 将地图头文件包含到我们的代码中以使用其功能。
- 将 iostream 头文件包含到我们的代码中以使用其功能。
- 将 std 命名空间包含到我们的代码中以便使用它的类而无需调用它。
- 调用 main() 函数。{ 标记函数主体的开始。
- 创建一个名为 m 的映射,其中键为整数,值也为整数。映射中已包含三个条目。
- 在映射 m 中插入一个新条目。键 5 和值 6 将被插入到映射中。
- 尝试对已存在的键进行输入。由于键 1 已存在于映射中,因此不会进行输入。
- 使用 insert_or_assign() 函数插入或修改现有条目。由于键 1 已存在,其值将被更改为 6。
- 在控制台上打印一些文本。“\t”字符创建一个水平空格,而“\n”字符将鼠标光标移动到下一行。
- 使用 for循环 创建一个名为 itr 的迭代器来迭代名为 m 的映射中的元素。
- 在控制台上打印映射 m 的值。“\t”字符在每个键和其对应的值之间创建一个水平空格。相反,“\n”字符在每次迭代后将鼠标光标移动到下一行。
- for 循环主体的结束。
- 程序成功完成后必须返回一个值。
- main() 函数体结束。
在地图中搜索
我们可以使用 `find()` 函数按键在映射中查找元素。如果找不到指定的键,该函数返回 `std::map::end`。否则,将返回找到的元素的迭代器。
例子3
#include <iostream> #include <string> #include <map> using namespace std; int main() { map<int, string> Students; Students.insert(std::pair<int, string>(200, "Alice")); Students.insert(std::pair<int, string>(201, "John")); std::map<int, string>::iterator it = Students.find(201); if (it != Students.end()) { std::cout << endl << "Key 201 has the value: => "<< Students.find(201)->second << '\n'; } }
输出:
以下是代码截图:
Code 说明:
- 将 iostream 头文件包含到我们的代码中以使用其功能而不会出现错误。
- 将字符串头文件包含到我们的代码中以便使用其功能而不会出现错误。
- 将地图头文件包含到我们的代码中以便使用其功能而不会出现错误。
- 将 std 命名空间包含到我们的代码中以便使用它的类而无需调用它。
- 调用 main() 函数。{ 标记 main() 函数体的开始。
- 创建一个名为 Students 的映射,其键为整数,值为字符串。
- 将值插入到映射 Students 中。键 200 和值 Alice 将被插入到映射中。
- 将值插入到映射 Students 中。键 201 和值 John 将被插入到映射中。
- 查找与键 201 关联的值。
- 使用 if 语句检查是否找到该键的值。
- 在控制台上打印密钥的值以及一些文本。
- if 语句主体结束。
- main() 函数体结束。
从地图中删除数据
我们可以使用 `erase()` 函数从映射中删除一个值。我们只需创建一个指向要删除元素的迭代器,然后将该迭代器传递给 `erase()` 函数即可。
例子4
#include <iostream> #include <string> #include <map> using namespace std; int main() { map<std::string, int> my_map; my_map.insert(std::make_pair("cow", 1)); my_map.insert(std::make_pair("cat", 2)); my_map["lion"] = 3; map<std::string, int>::iterator it = my_map.find("cat"); my_map.erase(it); for (map<string, int>::iterator it = my_map.begin(); it != my_map.end(); ++it) cout << (*it).first << ": " << (*it).second << endl; return 0; }
输出:
以下是代码截图:
Code 说明:
- 将 iostream 头文件包含到我们的代码中以使用其功能。
- 将字符串头文件包含到我们的代码中以使用其功能。
- 将地图头文件包含到我们的代码中以使用其功能。
- 将 std 命名空间包含到我们的代码中以便使用它的类而无需调用它。
- 调用 main() 函数。{ 标记 main() 函数体的开始。
- 创建一个名为 my_map 的映射,其键为字符串,值为整数。
- 将值插入到映射 my_map 中。键为 Cow,值 1 将插入到映射中。
- 将值插入到映射 my_map 中。键为 Cat,值 2 将插入到映射中。
- 将值 3 添加到映射 my_map 中,并以狮子为键。
- 创建一个迭代器来迭代映射 my_map 以寻找键 cat。
- 删除迭代器指向的元素。
- 使用迭代器从头到尾遍历映射 my_map 的元素。
- 在控制台上打印出地图my_map的内容。
- 程序成功完成后必须返回输出。
- main() 函数体结束。






