创建并初始化 map 容器
map 是 STL 中的一种关联容器,它提供了一种对{键,值}数据对进行保存和管理的能力。这种数据对是一对一成对出现的。
在 map 容器的内部,它是使用一棵红黑树实现的—— 一种非严格意义上的平衡二叉树,因为这棵树具有对数据自动排序的功能,所以 map 容器内部所有的数据都是有序的。正是这种特性,使得 map 容器在增加和删除节点时对迭代器的影响很小,除了被操作的当前操作节点外,对其他的节点都没有什么太大影响。因此 map 容器特别适用于保存和管理那些增加和删除操作比较多的大量数据。
map 容器同样是一个类模板,在使用的时候,需要根据它所要保存的数据,给定具体的数据类型参数对其进行实例化,以形成能够保存特定数据类型的 map 模板类。
// 引入 map 容器所在的头文件
#include <map>
// 使用 map 容器所在的名字空间 std
using namespace std;
// 创建一个 map 容器对象 mapEmp
// 这个容器需要保存“int-Employee”形式的数据对
// 所以以 int 和 Employee 作为 map 类模板的类型参数
map<int, Employee> mapEmp;
在创建一个 map 容器对象的同时,也可以使用初始化列表对其进行初始化,向其中添加必要的初始数据元素。
// 使用初始化列表对 map 容器进行初始化
map<int,Employee> mapEmp =
{ // map 容器的初始数据元素
{1001, Employee()}, // 默认的 Employee 对象
{1002, Employee("ChenLiangqiao")},
{1003, Employee("WangGang")}
};
map容器的操作函数
插入函数
例如:使用 insert()函数向容器中插入数据对。
使用pair(T,U)打包数据对
// 创建一个 Employee 对象
Employee emp1;
// 使用 pair<int, Employee>模板类建立员工号 1 和员工对象 emp1 的联系,形成数据对
// 将 pair<int, Employee>模板类创建的对象插入 map 容器中
mapEmp.insert(pair<int, Employee>(1, emp1 ));
使用value_type打包数据对
除了使用pair<T,U>
类模板来打包数据形成数据对之外,还可以使用 map 容器的value_type
类
型来实现数据的打包,完成数据的插入。例如:
// 使用 value_type 类型实现数据的插入
mapEmp.insert(map<int, Employee>::value_type(1, emp1 ));
使用[]操作符
除了使用 insert()函数向 map 容器插入数据之外,更简单的,我们可以把 map 容器看成是一个数组,直接利用 map 容器的“[ ]”操作符,以数据对的键作为索引值,用数据对中的值对其进行赋值,直接向 map 容器中插入数据对。例如:
// 向 mapEmp 容器中插入一个数据对( 1, emp1)
mapEmp[1] = emp1;
插入 map 容器的键必须是可以排序的。对于使用基本数据类型作为键的 map 容器,我们无须担心,因为它们本身已经支持“<”操作符排序。如果使用的是我们自定义的数据类型作为 map 容器的键,就需要重载其“<”操作符,以实现排序。
在进行插入操作的时候,我们必须保证插入的键在 map 容器中是唯一的,否则将导致插入操作失败。
查找
根据某个键找到它所对应的值进行访问。
遍历容器
// 利用 for 循环访问 map 容器中的所有数据
for( auto it = mapEmp.begin();
it != mapEmp.end(); ++it )
{
// 通过迭代器输出数据对的键和值
cout<<"当前员工号是: "<<it->first<<endl;
cout<<"姓名: "<<it->second.GetName()<<endl;
cout<<"工资: "<<it->second.GetSalary()<<endl;
}
map 容器的迭代器对象实际上是一个 pair 对象
,它包括两个数据:it->first
和 it->second
,分别代表键以及跟这个键相对应的值。这里, map 容器中保存的值是 Employee 对象,所以“it->second”实际上就是 Employee 对象,可以直接调用它的成员函数获得相应的数据。
find()查找某一个键
// 定义要查找的键
int nKey = 1;
// 使用 find()函数查找键,返回指向拥有这个键的数据对的迭代器
// 如果 map 容器中没有这个键,则返回指向容器末尾位置的迭代器
auto it = mapEmp.find( nKey );
// 查看迭代器是否指向容器末尾位置,以此判断是否找到相应的数据对
if (mapEmp.end() == it )
{
// 如果迭代器指向容器末尾位置,就表示没有找到对应的数据对
cout<<"无法找到键为"<<nKey<<"的数据对"<<endl;
}
else
{
// 如果迭代器指向其他位置,则表示找到相应的数据对,
// find()函数返回的迭代器指向的就是这个数据对的位置
cout<<"找到键为"<<nKey<<"的数据对"<<endl;
// 通过迭代器访问这个数据对的值,也就是 Employee 对象
cout<<"姓名: "<<it->second.GetName()<<endl;
cout<<"工资: "<<it->second.GetSalary()<<endl;
}
访问某个范围内的数据对
// 定义键的起止范围
int nFromKey = 1;
int nToKey = 1000;
// 用迭代器表示起始位置和终止位置
auto itfrom = mapEmp.lower_bound( nFromKey );
auto itto = mapEmp.upper_bound( nToKey );
// 判断是否找到正确的范围
if( mapEmp.end() != itfrom && mapEmp.end() != itto )
{
// 输出范围内的所有数据
for( auto it = itfrom;
it != itto; ++it )
{
cout<<"当前员工号是: "<<it->first<<endl;
cout<<"姓名: "<<it->second.GetName()<<endl;
cout<<"工资: "<<it->second.GetSalary()<<endl;
}
// 删除范围内的所有数据
mapEmp.erase( itfrom, itto );
}
分别使用了lower_bound()
函数和upper_bound()
函数来获得指向这个范围的起始位置和终止位置的迭代器,然后通过这两个迭代器所界定的范围来对某个键范围中的数据进行访问。
最后,我们还利用 erase()函数实现了对这个键范围内所有数据的删除。