map简介
Map是STL的一个关联容器,它的特点是增加和删除节点对迭代器的影响很小,除了那个操作节点,对其他的节点都没有什么影响。对于迭代器来说,可以修改实值,而不能修改key。它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。这里说下map内部数据的组织,map内部自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处。
Map初始化
(1) 默认构造: map<Key, value> m; 构造一个空的map,注意,必要时要给出模板参数中的 Compare。需要时给出 Alloc
(2) 范围构造: map<key, value> m(iterator first, iteratorlast); 将迭代器[frist, last)范围内的元素填入map中
(3) 拷贝构造: map<key, value> m(cosnt map& m2); 用m2构造m
(4) 初始化列表构造: map<key, value>m(initializer_list<value_type> il)
由于map 的 value_type 是 pair类型,所以要构造成pair作为列表,这是三种构造 pair的方式
map<key, value> m{{key k1,value v1},{k2, v2}, ...} // 通过 {}构造 pair
map<key, value>m{make_pair(key k1, value v1), make_pair(k2, v2), ...} // 通过make_pair() 函数构造 pair
map<key, value>m{pair<key, value>(k1, v1), pair<key, value>(k2, v2), ...} // 通过类型转换构造pair
map常用函数
begin() 返回指向map头部的迭代器
clear() 删除所有元素
count() 返回指定元素出现的次数
empty() 如果map为空则返回true
end() 返回指向map末尾的迭代器
equal_range() 返回特殊条目的迭代器对
erase() 删除一个元素
find() 查找一个元素
get_allocator() 返回map的配置器
insert() 插入元素
key_comp() 返回比较元素key的函数
lower_bound() 返回键值>=给定元素的第一个位置
max_size() 返回可以容纳的最大元素个数
rbegin() 返回一个指向map尾部的逆向迭代器
rend() 返回一个指向map头部的逆向迭代器
size() 返回map中元素的个数
swap() 交换两个map
upper_bound() 返回键值>给定元素的第一个位置
value_comp() 返回比较元素value的函数
这里我们着重讲解erase函数
//测试erase函数
map<int, int>::iterator it2 = mymap.begin();
while(it2 != mymap.end())
{
if(it2->second == 12)
{
mymap.erase(it2++);
/*
该方法中利用了后缀++的特点,这个时候执行mapInt.erase(it2++);这条语句分为三个过程
1、先把it2的值赋值给一个临时变量做为传递给erase的参数变量
2、因为参数处理优先于函数调用,所以接下来执行了it2++操作,也就是it2现在已经指向了下一个地址。
3、再调用erase函数,释放掉第一步中保存的要删除的it2的值的临时变量所指的位置。
前缀++和后缀++的返回值一个是迭代器引用,一个却是迭代器传值.简单来说,
前缀++返回的便是传参进来的迭代器,自然可以返回迭代器本身的引用,
然而后缀++返回的是一个函数内部的临时变量,在函数执行完后便析构了,
必然不能传引用。注意既然是通过传值的方式返回,对其返回值的修改对于原it2是没有影响的
*/
}
it2++;
}
print(mymap);
erase删除的是迭代器指向的数据。
还有find函数,函数原型是iterator find (const key_type& k); 返回值要用迭代器iterator接收
代码如下:
//测试find函数 函数原型 iterator find (const key_type& k); 返回值用迭代器接收
map<int, int>::iterator it1 = mymap.find(1);
cout << "返回元素" << it1->second << endl;
一个测试map函数的简单小程序
#include <iostream>
#include <map>
using namespace std;
//抽象一个print函数,用来打印map中的值
void print(map<int, int> mymap)
{
map<int, int> ::iterator itor = mymap.begin();
while(itor != mymap.end())
{
cout << "打印map的数据" << itor->first << " " << itor->second << endl;
itor++;
}
}
int main()
{
map<int, int> mymap;
cout << "初始化前map的大小: " << mymap.size() << endl; //显示初始化前map的大小
//赋值时故意key值没有按顺序输入,但是打印时确实按顺序输出,说明map内部有自带的排序的结构,即红黑树,这样给我们启示:查找数据会变得简单
mymap[0] = 10;
mymap[2] = 12;
//mymap[1] = 11;
mymap.insert(map<int, int>::value_type(1,11));
/*
以上赋值方法开销较大,不太好,如输入 mymap[1] = 11时,需要依次比较map中存在的key值,按大小进行插入。可以按照以下的方法进行赋值
mymap.insert(map<int, int>::value_type(1,11));
*/
cout << "初始化后map的大小:" << mymap.size() << endl; 显示初始化后map的大小
//用迭代器遍历map的数据
map<int, int> ::iterator itor = mymap.begin();
while(itor != mymap.end())
{
//通过map对象的方法获取的iterator数据类型是一个std::pair对象,
//包括两个数据 iterator->first 和 iterator->second 分别代表关键字和存储的数据
cout << "打印map的数据" << itor->first << " " << itor->second << endl;
itor++;
}
//以下代码用来测试map的相关函数
/*
mymap.clear(); //用来清除map中的所有元素
cout << "调用clear函数之后map的大小" << mymap.size() << endl;
*/
//测试find函数 函数原型 iterator find (const key_type& k); 返回值用迭代器接收
map<int, int>::iterator it1 = mymap.find(1);
cout << "返回元素" << it1->second << endl;
//测试erase函数
map<int, int>::iterator it2 = mymap.begin();
while(it2 != mymap.end())
{
if(it2->second == 12)
{
mymap.erase(it2++);
/*
该方法中利用了后缀++的特点,这个时候执行mapInt.erase(it2++);这条语句分为三个过程
1、先把it2的值赋值给一个临时变量做为传递给erase的参数变量
2、因为参数处理优先于函数调用,所以接下来执行了it2++操作,也就是it2现在已经指向了下一个地址。
3、再调用erase函数,释放掉第一步中保存的要删除的it2的值的临时变量所指的位置。
前缀++和后缀++的返回值一个是迭代器引用,一个却是迭代器传值.简单来说,
前缀++返回的便是传参进来的迭代器,自然可以返回迭代器本身的引用,
然而后缀++返回的是一个函数内部的临时变量,在函数执行完后便析构了,
必然不能传引用。注意既然是通过传值的方式返回,对其返回值的修改对于原it2是没有影响的
*/
}
it2++;
}
print(mymap);
return 0;
}
运行结果为