目录
一.何为单映射容器map
在简绍这map容器之前我们先来看另一个概念——键值对。
所谓的键值对是由 键(key) 和 值(value) 两部分组成的,一个键对应一个值,值可以重复,但是键不能重复。例如我们可以将身份证号对应为键(key),而某个身份证号对应的名字称为值(value),而我们都知道身份证号是不可以重复的,人手一个,但是名字却可以重复。而我们所要简绍的map中的数据就是以键值对的形式存在的。
单映射容器map的底层都为红黑树,所需的头文件为#include<map>。
接着我们来看一下底层的二叉树具体是怎么存储map容器中的数据的
我们看到map底层二叉树的一个节点被分为3个域,分别是左孩子域,右孩子域和数据域(映射域),而这里的映射域中存放的就是结构体pair定义的映射关系,也就是我们上面提到过的键值对,我们来看一下结构体pair的类型。
#include<iostream>
#include<iterator>
#include<algorithm>
#include<map>
int main()
{
std::map<int, int> mymap;//创建一个map容器
std::cout <<typeid(std::map<int,int>::value_type).name()<< std::endl;
return 0;
}
我们看到在结构体pair中,键(key)是常量,而值(value)是变量。
二.map容器的使用方法
#include<iostream>
#include<iterator>
#include<algorithm>
#include<map>
template<typename Container>
void Show(Container& con)
{
typename Container::iterator it = con.begin();
while (it != con.end())
{
std::cout << it->first << "-" << it->second << std::endl;
it++;
}
}
int main()
{
std::map<int, int> mymap;//创建一个map容器
std::pair<int, int> p1(1, 11);
mymap.insert(p1);
std::pair<int, int> p2(1, 1111);
mymap.insert(p2);//没有处理
std::cout << "第一次打印:"<<std::endl;
Show(mymap);
std::map<int, int>::value_type val(2, 22);
mymap.insert(val);
mymap[3] = 33;//插入
mymap[1] = 111;//修改
std::cout << "第二次打印:" << std::endl;
Show(mymap);
//map 类中 find查询 二分查找 O(log2 n)
std::map<int, int>::iterator fit = mymap.find(2);
if (fit != mymap.end())
{
std::cout << "第三次打印:" << std::endl;
std::cout << fit->first << fit->second << std::endl;
//fit->first 代表迭代器所迭代的映射关系中 key fit->second 代表迭代器所迭代的映射关系中 value
mymap.erase(fit);
}
std::cout << "第四次打印:" << std::endl;
Show(mymap);
return 0;
}
其中
std::pair<int, int> p1(1, 11);
mymap.insert(p1);
这两句的意思是,首先利用结构体pair创建一个映射关系(键值对),其键(key)为1,值(value)为11,接着将这一映射关系(键值对)插入到map容器中。我们知道map的底层为红黑树,所以map容器中不存在定点插入,因为每插入一个数据,红黑树就要进行相应的调整。
std::pair<int, int> p2(1, 1111);
mymap.insert(p2);//没有处理
我们知道,键值对中的键(key)必须唯一,前面我们已经将映射关系(键值对)1->11,插入到map容器中了,所以就算这时我们重新创建一个映射关系(键值对)1->11,并将它插入到map容器当中,系统也会将它忽略掉,不作任何处理,这一点我们可以从上面打印的结果中可以看到。
std::map<int, int>::value_type val(2, 22);
mymap.insert(val);
这是另一种向map容器中插入的方法,使用这种方法时,我们可以不必利用结构体pair创建映射关系,而是利用value_type做插入。
mymap[3] = 33;//插入
mymap[1] = 111;//修改
我们看到这两条语句大径相同,但各自最终的结果却是天壤地别。因为我们之前只向map容器中插入了键值对 1->11 和 2->22,而没有插入过键(key)为3的键值对,所以mymap[3]=33在这里的意思是向map容器中插入映射关系(键值对)3->33。因为之前已经插入过键值对1->11了,所以mymap[1]=111的意思是,将键值对1->11的值(value)11改为111,所以最后键(key)所对应的值变为了111。
std::map<int, int>::iterator fit = mymap.find(2);
if (fit != mymap.end())
{
std::cout << "第三次打印:" << std::endl;
std::cout << fit->first << fit->second << std::endl;
//fit->first 代表迭代器所迭代的映射关系中 key fit->second 代表迭代器所迭代的映射关系中 value
mymap.erase(fit);
}
在这里map类中会提供一个查找函数find,时间复杂度为O(log2 n)因为是使用的是二分查找法,参数是要查找的键(key),例如这里我们利用find查找键(key)为2的键值对的位置,如果找到就将键(key)为2的键值对的位置传递给迭代器fit,如果找不到,即键(key)为2的键值对不存在,那么就把map容器的.end()位置传给迭代器fit。而 fit->first代表当前迭代器所迭代的映射关系中的键(key),fit->second代表当前迭代器所迭代的映射关系中的值(value)。而erase的意思是删除当前迭代器所迭代的键值对(映射关系)。
最后我们看到利用泛型算法Show打印的map容器中的数据都是从小到大排序的,这是因为map容器的底层为红黑树,红黑树是默认按中序遍历来对数据进行从小到大的排序的。