文章目录
C++ map
Map是STL [1] 的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。
map容器属于关联容器中的有序容器。之前所写的srting、vector、list、queue、deque都属于顺序容器;我们接下来所学的map,set都是关联容器。
关联容器的特点是:键—值 对,key—value;顺序容器直接是实值,没有代表性的键值。例如,1—1号学生个人信息,我们在容器中查找1号学生信息,我们只需要找到1的位置就能查询到1号学生信息。
定义
map是键值保存,高效访问,通过键值排序,通过键值查找。
特点:
- 高效访问,比如容器中有一百万个数据量,map是1~20次找到,而list则是O(log(n))次。缺点:插入效率低于链表,因为涉及到排序
- 键值不能重复
map和multimap十分相似,区别在于mao容器中元素的关键字不能重复。multimap有的成员函数,map都有。此外,mao还有成员函数operator[]:T & operator[] (Key k);
该成员函数返回 first 值为 k 的元素的 second 部分的引用。如果容器中没有元素的 first 值等于 k,则自动添加一个 first 值为 k 的元素。如果该元素的 second 成员变量是一个对象,则用无参构造函数对其初始化。
头文件
需要引用一个头文件#include<map>
#include<iostream>
#include<map>
using namespace std;
构造函数
语法一:
pair<iterator, bool> insert( const pair<KEY_TYPE,VALUE_TYPE> &val );
只有在val不存在时插入val。返回值是一个指向被插入元素的迭代器和一个描述是否插入的bool值。
pair<键,值>
键值不能重复,实值可以重复;
输出键值用first,实值用second;
void fun(pair<int,char> pr)
{
cout << pr.first << " " << pr.second << endl;
}
void MapConstruct()
{
typedef pair<int,char> in_pair;
map<int , char> mp; // < / >
mp.insert(pair<int,char>(1,'a'));//插入方法一
mp.insert(in_pair(2,'b'));//插入方法二
for_each(mp.begin(),mp.end(),fun);
}
输出结果为:
我们知道在map容器中键值不能有重复的,那我们实验一下,如果有重复的,输出结果会是什么?怎样才能报错;
typedef pair<int,char> in_pair;
map<int , char> mp; // < / >
mp.insert(pair<int,char>(1,'a'));
mp.insert(in_pair(2,'a'));
mp.insert(in_pair(2,'b')); //此处,存在两个键值为2的元素
for_each(mp.begin(),mp.end(),fun);//遍历输出
输出结果:
我们不难发现只有第一个键值为2 的成功输出出来,那么另一个我们怎么判定是map容器内存在重复元素;我们通过定义pair<map<int,char>::iterator,bool>pr;
,通过输出bool的真假去判断键值是否重复
typedef pair<int,char> in_pair;
pair<map<int,char>::iterator,bool>pr;
map<int , char> mp; // < / >
mp.insert(pair<int,char>(1,'a'));
pr = mp.insert(in_pair(2,'a'));
cout << pr.second << endl;
pr = mp.insert(in_pair(2,'b'));
cout << pr.second << endl;
输出结果:
由此我们看到,第一个插入成功bool为1,第二个因为键值重复导致失败所以为0.
语法二:
iterator insert( iterator pos, const pair<KEY_TYPE,VALUE_TYPE> &val );
插入val到pos的后面,然后返回一个指向这个元素的迭代器。
使用迭代器进行插入,迭代器可以++,但是不可以+2,+3之类的;由于map内部会自动排序,不管用迭代器插入到任意位置,map容器也会将其排序,插入到其应有的序列中去
typedef pair<int,char> in_pair;
pair<map<int,char>::iterator,bool>pr;
map<int , char> mp; // < / >
mp.insert(pair<int,char>(1,'a'));
pr = mp.insert(in_pair(3,'a'));
// cout << pr.second << endl;
pr = mp.insert(in_pair(4,'b'));
// cout << pr.second << endl;
pr = mp.insert(in_pair(5,'b'));
pr = mp.insert(in_pair(6,'b'));
pr = mp.insert(in_pair(7,'b'));
pr = mp.insert(in_pair(9,'b'));
map<int,char>::iterator ite = mp.begin();
ite++;
ite++;
ite++;
ite++; //插入第4个位置
mp.insert(ite, in_pair(2,'b'));
for_each(mp.begin(),mp.end(),fun);
输出结果:
看出我们本应该在第四个位置插入2,b,却被其自动插入到第二个位置,并以键值按照升序排列。
语法三:
void insert( input_iterator start, input_iterator end );
插入start到end的元素到map中。
map<int,char> mp1;
mp1.insert(in_pair(8,'d'));
mp1.insert(in_pair(10,'d'));
mp.insert(mp1.begin(),mp1.end());
输出结果:
用另一个map容器,定义一个新的容器
map<int,char>mp2(mp1); //将mp1的值初始化给mp2
map<int,char> mp3(mp2.begin()++,mp2.end()--);
//将mp2从第二个到倒数第二个初始化给mp3
属性
语法:
size_type size();
size()函数返回map中保存的元素个数。
typedef pair<int,char> in_pair;
map<int,char> mp;
mp.insert(in_pair(1,'a'));
mp.insert(in_pair(2,'b'));
mp.insert(in_pair(3,'c'));
mp.insert(in_pair(4,'d'));
mp.insert(in_pair(5,'e'));
cout << mp.size() << endl;
输出结果:
语法:
size_type count( const KEY_TYPE &key );
我们常用count()判断map中是否存在目标键值。
typedef pair<int,char> in_pair;
map<int,char> mp;
mp.insert(in_pair(1,'a'));
mp.insert(in_pair(2,'b'));
mp.insert(in_pair(3,'c'));
mp.insert(in_pair(4,'d'));
mp.insert(in_pair(5,'e'));
cout << mp.count(2) << endl;//存在键值2
cout << mp.count(7) << endl;//不存在键值7
输出结果:
由此可知,mp里存在键值为2的元素,不存在键值为7的元素。
语法:
bool empty();
empty()函数返回真(true)如果map为空,否则返回假(false)。
cout << empty() << endl;
语法:
iterator begin();
begin()函数返回一个迭代器指向map的第一个元素。
语法:
iterator end();
end()函数返回一个迭代器指向map的尾部。
输出
需要加头文件#include<algorithm>
typedef pair<int,char> in_pair;
map<int,char> mp;
mp.insert(in_pair(1,'a'));
mp.insert(in_pair(2,'b'));
mp.insert(in_pair(3,'c'));
mp.insert(in_pair(4,'d'));
mp.insert(in_pair(5,'e'));
map<int ,char>::iterator ite = mp.begin();
for(ite; ite != mp.end(); ite++)
{
cout << ite->first << " " << ite->second << endl;
}
遍历结果:
操作
1.增
2.改
键值不能改,实值可以改
3.查
关于count()前面有写道。
语法:
iterator find( const KEY_TYPE &key );
find()函数返回一个迭代器指向键值为key的元素,如果没找到就返回指向map尾部的迭代器。
尾部迭代器 == end(),我们可以判断说法是否正确,如下:
typedef pair<int,char> in_pair;
map<int,char> mp;
mp.insert(in_pair(1,'a'));
mp.insert(in_pair(2,'b'));
map<int,char>::iterator ite1 = mp.find(2);
cout << ite1->first << " " << ite1->second << endl;
if( mp.end() == mp.find(7))
{
cout << "判断正确" << endl;
}
输出结果:
4.删
语法:
void erase( iterator pos );
void erase( iterator start, iterator end );
size_type erase( const KEY_TYPE &key );
erase()函数
- 删除在pos位置的元素
- 删除在start和end之间的元素
- 删除那些值为key的所有元素。
void MapDel()
{
typedef pair<int,char> in_pair;
map<int,char> mp;
mp.insert(in_pair(1,'a'));
mp.insert(in_pair(2,'b'));
mp.insert(in_pair(3,'c'));
mp.insert(in_pair(4,'d'));
mp.insert(in_pair(5,'e'));
mp.insert(in_pair(6,'f'));
map<int,char>::iterator ite = mp.begin();
map<int,char>::iterator ite1 = mp.begin();
ite++;
ite++; //指向第三个元素;
mp.erase(ite); //删除迭代器指向的元素
//第一次删除后,有:
//1 a
//2 b
//4 d
//5 e
//6 f
ite1++;
ite1++;
ite1++; //指向第四个元素;
mp.erase(ite1,mp.end());//删除第四个到最后一个之间的元素
mp.erase(1); //删除键值为1的元素
ite = mp.begin();
for(ite;ite != mp.end(); ite++)
{
cout << ite ->first << " " << ite->second << endl;
}
}
输出结果:
语法:
void clear();
clear()函数删除map中的所有元素。
mp.clear();
其他函数
语法:
void swap( map &obj );
swap()交换obj和现map中的元素。
typedef pair<int,char> in_pair;
map<int,char> mp;
mp.insert(in_pair(1,'a'));
mp.insert(in_pair(5,'e'));
mp.insert(in_pair(3,'c'));
mp.insert(in_pair(4,'d'));
mp.insert(in_pair(2,'b'));
mp.insert(in_pair(6,'f'));
map<int,char>::iterator ite = mp.begin();
for(ite;ite != mp.end(); ite++)
{
cout << ite ->first << " " << ite->second << endl;
}
输出结果:
需要头文件#include<functional>
以及模板参数列表 greater< int>
从而改变map排序顺序
typedef pair<int,char> in_pair;
map<int,char> mp;
mp.insert(in_pair(1,'a'));
mp.insert(in_pair(5,'e'));
mp.insert(in_pair(3,'c'));
mp.insert(in_pair(4,'d'));
mp.insert(in_pair(2,'b'));
mp.insert(in_pair(6,'f'));
map<int,char>::iterator ite = mp.begin();
for(ite;ite != mp.end(); ite++)
{
cout << ite ->first << " " << ite->second << endl;
}
cout << endl;
map<int,char,greater<int> > mp1;//模板参数列表,是个类型
mp1.insert(in_pair(1,'a'));
mp1.insert(in_pair(5,'e'));
mp1.insert(in_pair(3,'c'));
mp1.insert(in_pair(4,'d'));
mp1.insert(in_pair(2,'b'));
mp1.insert(in_pair(6,'f'));
map<int,char,greater<int> >::iterator ite1 = mp1.begin();
//注意此处的双>>一定要分开 > >
for(ite1;ite1 != mp1.end(); ite1++)
{
cout << ite1 ->first << " " << ite1->second << endl;
}
输出:
语法:
iterator lower_bound( const KEY_TYPE &key );
lower_bound()函数返回一个迭代器,指向map中键值>=key的第一个元素。
比如:我在上面这一列中寻找键值为9的元素,发现没有目标键值,由于lower_bound()函数中定义返回>=key的第一个元素,因此迭代器返回的是键值为10 的元素;若寻找键值为6的元素,那么直接返回6.
语法:
iterator upper_bound( const KEY_TYPE &key );
upper_bound()函数返回一个迭代器,指向map中键值>key的第一个元素。
根据上图,返回键值都大于其目标键值。若寻找键值为6的元素,那么直接返回8.
typedef pair<int,char> in_pair;
map<int,char> mp2;
mp2.insert(in_pair(1,'a'));
mp2.insert(in_pair(3,'c'));
mp2.insert(in_pair(5,'e'));
cout << mp2.lower_bound(3)->first << endl;
cout << mp2.upper_bound(3)->first << endl;
输出结果:
#include<iostream>
#include<map>
#include<algorithm>
#include<functional>
using namespace std;
void fun(pair<int,char> pr)
{
cout << pr.first << " " << pr.second << endl;
}
void MapConstruct()
{
typedef pair<int,char> in_pair;
pair<map<int,char>::iterator,bool>pr;
map<int , char> mp; // < / >
mp.insert(pair<int,char>(1,'a'));
pr = mp.insert(in_pair(3,'a'));
// cout << pr.second << endl;
pr = mp.insert(in_pair(4,'b'));
// cout << pr.second << endl;
pr = mp.insert(in_pair(5,'b'));
pr = mp.insert(in_pair(6,'b'));
pr = mp.insert(in_pair(7,'b'));
pr = mp.insert(in_pair(9,'b'));
map<int,char>::iterator ite = mp.begin();
ite++;
ite++;
ite++;
ite++;
mp.insert(ite, in_pair(2,'b'));
map<int,char> mp1;
mp1.insert(in_pair(8,'d'));
mp1.insert(in_pair(10,'d'));
mp.insert(mp1.begin(),mp1.end());
map<int,char> mp2(mp1);
map<int,char> mp3(mp2.begin()++,mp2.end()--);
for_each(mp.begin(),mp.end(),fun);
}
void MapAttribute()
{
typedef pair<int,char> in_pair;
map<int,char> mp;
mp.insert(in_pair(1,'a'));
mp.insert(in_pair(2,'b'));
mp.insert(in_pair(3,'c'));
mp.insert(in_pair(4,'d'));
mp.insert(in_pair(5,'e'));
cout << mp.size() << endl;
cout << mp.count(2) << endl;
cout << mp.count(7) << endl;
map<int,char>::iterator ite1 = mp.find(2);
cout << ite1->first << " " << ite1->second << endl;
if( mp.end() == mp.find(7))
{
cout << "判断正确" << endl;
}
// cout << mp.empty() << endl;
//
// map<int ,char>::iterator ite = mp.begin();
//
// for(ite; ite != mp.end(); ite++)
// {
// cout << ite->first << " " << ite->second << endl;
//
// }
}
void MapDel()
{
typedef pair<int,char> in_pair;
map<int,char> mp;
mp.insert(in_pair(1,'a'));
mp.insert(in_pair(2,'b'));
mp.insert(in_pair(3,'c'));
mp.insert(in_pair(4,'d'));
mp.insert(in_pair(5,'e'));
mp.insert(in_pair(6,'f'));
map<int,char>::iterator ite = mp.begin();
map<int,char>::iterator ite1 = mp.begin();
ite++;
ite++; //指向第三个元素;
mp.erase(ite); //删除迭代器指向的元素
//第一次删除后,有:
//1 a
//2 b
//4 d
//5 e
//6 f
ite1++;
ite1++;
ite1++; //指向第四个元素;
mp.erase(ite1,mp.end());//删除第四个到最后一个之间的元素
mp.erase(1); //删除键值为1的元素
ite = mp.begin();
for(ite;ite != mp.end(); ite++)
{
cout << ite ->first << " " << ite->second << endl;
}
}
void MapOther()
{
typedef pair<int,char> in_pair;
map<int,char> mp;
mp.insert(in_pair(1,'a'));
mp.insert(in_pair(5,'e'));
mp.insert(in_pair(3,'c'));
mp.insert(in_pair(4,'d'));
mp.insert(in_pair(2,'b'));
mp.insert(in_pair(6,'f'));
map<int,char>::iterator ite = mp.begin();
for(ite;ite != mp.end(); ite++)
{
cout << ite ->first << " " << ite->second << endl;
}
cout << endl;
map<int,char,greater<int> > mp1;//模板参数列表,是个类型
mp1.insert(in_pair(1,'a'));
mp1.insert(in_pair(5,'e'));
mp1.insert(in_pair(3,'c'));
mp1.insert(in_pair(4,'d'));
mp1.insert(in_pair(2,'b'));
mp1.insert(in_pair(6,'f'));
map<int,char,greater<int> >::iterator ite1 = mp1.begin();
for(ite1;ite1 != mp1.end(); ite1++)
{
cout << ite1 ->first << " " << ite1->second << endl;
}
typedef pair<int,char> in_pair;
map<int,char> mp2;
mp2.insert(in_pair(1,'a'));
mp2.insert(in_pair(5,'e'));
mp2.insert(in_pair(3,'c'));
mp2.insert(in_pair(6,'f'));
cout << mp2.lower_bound(3)->first << endl;
cout << mp2.upper_bound(3)->first << endl;
}
int main()
{
//MapConstruct();
//MapAttribute();
//MapDel();
MapOther();
system("pause");
return 0;
}