现在,对于map的描述的博客已经很多了 但是作为一个很懒的人,决定花点时间把这些整理出来。
1.map简介
map是一类关联式容器,它是模板类。关联的本质在于元素的值与某个特定的键相关联,而并非通过元素在数组中的位置类获取。它的特点是增加和删除节点对迭代器的影响很小,除了操作节点,对其他的节点都没有什么影响。对于迭代器来说,不可以修改键值,只能修改其对应的实值。
2.map的功能
- 自动建立Key - value的对应。key 和 value可以是任意你需要的类型,但是需要注意的是对于key的类型,唯一的约束就是必须支持<操作符。
- 根据key值快速查找记录,查找的复杂度基本是Log(N),如果有1000个记录,最多查找10次,1,000,000个记录,最多查找20次。
- 快速插入Key - Value 记录。
- 快速删除记录
- 根据Key 修改value记录。
3.在map中添加元素
给map中添加元素主要有两种方法:
- 使用下标操作符获取元素,然后给元素赋值
For example:
map<string, int> word_count; // 定义了一个空的map对象word_count;
word_count["Anna"] = 1;
程序说明:
1.在word_count中查找键为Anna的元素,没有找到.
2.将一个新的键-值对插入到word_count中,他的键是const string类型的对象,保存Anna。而他的值则采用直初始化,这就意味着在本例中指为0.
3.将这个新的键-值对插入到word_count中
4.读取新插入的元素,并将她的值赋为1.
使用下标访问map与使用下标访问数组或者vector的行为是截然不同的:使用下标访问不存在的元素将导致在map容器中添加一个新的元素,他的键即为该下标值。
- 使用map::insert方法添加元素
map容器提供的insert操作:
1. map.insert(e) : e是一个用在map中的value_type类型的值。如果键不存在,则插入一个值为e.second的新元素;如果键在map中已经存在,那么不进行任何操作。该函数返回一个pair类型,该pair类型的first元素为当前插入e的map迭代器,pair的second类型是一个bool类型,表示是否插入了该元素。
2. map.insert(beg, end) : beg和end是迭代器,返回void类型
3. map.insert(iter, e) : e是value_type类型的值,如果e.first不在map中,则创建新元素,并以迭代器iter为起点搜索新元素存储的位置,返回一个迭代器,指向map中具有给定键的元素。
For example:
word_count.insert(map<sting, int>::value_type("Anna", 1));
返回值:如果该键已在容器中,则其关联的值保持不变,返回的bool值为true。
4.查找并获取map中的元素
使用下标获取元素存在一个很危险的副作用:如果该键不在map容器中,那么下标操作会插入一个具有该键的新元素。
因此引入map对象的查询操作:
map.count(k) : 返回map中键k的出现次数(对于map而言,由于一个key对应一个value,因此返回只有0和1,因此可以用此函数判断k是否在map中)
map.find(k) : 返回map中指向键k的迭代器,如果不存在键k,则返回超出末端迭代器。
For example:
int occurs = 0;
if( word_count.cout("foobar") )
occurs = word_count["foobar"];
int occurs = 0;
map<string, int>::iterator it = word_count.find("foobar");
if( it != word_count.end() )
occurs = it ->second;
5.从map中删除元素
移除某个map中某个条目用erase()
该成员方法的定义如下:
- iterator erase(iterator it); //通过一个条目对象删除
- iterator erase(iterator first, iterator last); //删除一个范围
- size_type erase(const Key& key); //通过关键字删除
像大多数容器一般,可以使用迭代器对map进行遍历
map<string,int> ::iterator it;
it->first表示map的键key,it->second表示map的value;
7.关于map的排序
map的排序默认为key的排序,当然也可以通过修改默认的排序函数来DIY自己的排序
例如
struct CmpByKeyLength {
bool operator()(const string& k1, const string& k2) {
return k1.length() < k2.length();
}
};
map<string,int,CmpByKeyLength> name_score_map;
这样后新建的map就是按照Key值的长度排序的。
本文链接地址: http://blog.csdn.net/iicy266/article/details/11906189
在<utility>头文件中,还为pair重载了 < 运算符, 具体实现如下:
- template<class _T1, class _T2>
- inline bool
- operator<(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
- { return __x.first < __y.first
- || (!(__y.first < __x.first) && __x.second < __y.second); }
重点看下其实现:
- __x.first < __y.first || (!(__y.first < __x.first) && __x.second < __y.second)
这个less在两种情况下返回true,第一种情况:__x.first < __y.first 这个好理解,就是比较key,如果__x的key 小于 __y的key 则返回true。
第二种情况有点费解: !(__y.first < __x.first) && __x.second < __y.second
当然由于||运算具有短路作用,即当前面的条件不满足是,才进行第二种情况的判断 。第一种情况__x.first < __y.first 不成立,即__x.first >= __y.first 成立,在这个条件下,我们来分析下 !(__y.first < __x.first) && __x.second < __y.second
!(__y.first < __x.first) ,看清出,这里是y的key不小于x的key ,结合前提条件,__x.first < __y.first 不成立,即x的key不小于y的key即: !(__y.first < __x.first) && !(__x.first < __y.first ) 等价于 __x.first == __y.first ,也就是说,第二种情况是在key相等的情况下,比较两者的value(second)。
具体实现如下:
#include<bits/stdc++.h>
using namespace std;
struct CmpByKeyLength {
bool operator()(const string& k1, const string& k2) {
return k1.length() < k2.length();
}
};
typedef pair<string,int> PAIR;
int main()
{
map<string,int,CmpByKeyLength> name_score_map;
map<string,int>::iterator it;
name_score_map["LiMin"] = 90;
name_score_map["ZiLinMi"] = 79;
name_score_map["BoB"] = 92;
name_score_map.insert(make_pair("Bing",99));
name_score_map.insert(make_pair("Albert",86));
vector<PAIR> name_score_vec(name_score_map.begin(), name_score_map.end());
sort(name_score_vec.begin(), name_score_vec.end());
//通过自定义比较函数来排序
for(it=name_score_map.begin();it!=name_score_map.end();it++)
{
cout<<it->first<<" "<<it->second<<endl;
}
//利用vector来排序
for(int i=0;i<name_score_vec.size();i++)
{
cout<< name_score_vec[i].first<<" "<<name_score_vec[i].second << endl;
}
return 0;
}