1.从map中读取元素而又不插入该元素
find操作返回指向元素的迭代器,如果该元素不存在,则返回end迭代器:
int occurs = 0 ;
map<string, int>::iterator it = word_count.find("foobar") ;
if (it != word_count.end())
{
occurs = it->second ;
}
2.人工定制的map排序方法:
3.定义map的排序方式:
typedef std::multimap<double,CStdString,less<double>>ADPRIORITY_MAP;
4. 排序
这里要讲的是一点比较高深的用法了,排序问题,STL中默认是采用小于号来排序的,以上代码在排序上是不存在任何问题的,因为上面的关键字是int型,它本身支持小于号运算,在一些特殊情况,比如关键字是一个结构体,涉及到排序就会出现问题,因为它没有小于号操作,insert等函数在编译的时候过不去,下面给出两个方法解决这个问题
第一种:小于号重载,程序举例
#include <map>
#include <string>
Using namespace std;
Typedef struct tagStudentInfo
{
Int nID;
String strName;
}StudentInfo, *PStudentInfo; //学生信息
Int main()
{
int nSize;
//用学生信息映射分数
map<StudentInfo, int>mapStudent;
map<StudentInfo, int>::iterator iter;
StudentInfo studentInfo;
studentInfo.nID = 1;
studentInfo.strName = “student_one”;
mapStudent.insert(pair<StudentInfo, int>(studentInfo, 90));
studentInfo.nID = 2;
studentInfo.strName = “student_two”;
mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));
for (iter=mapStudent.begin(); iter!=mapStudent.end(); iter++)
cout<<iter->first.nID<<endl<<iter->first.strName<<endl<<iter->second<<endl;
}
以上程序是无法编译通过的,只要重载小于号,就OK了,如下:
Typedef struct tagStudentInfo
{
Int nID;
String strName;
Bool operator < (tagStudentInfo const& _A) const
{
//这个函数指定排序策略,按nID排序,如果nID相等的话,按strName排序
If(nID < _A.nID) return true;
If(nID == _A.nID) return strName.compare(_A.strName) < 0;
Return false;
}
}StudentInfo, *PStudentInfo; //学生信息
第二种:仿函数的应用,这个时候结构体中没有直接的小于号重载,程序说明
#include <map>
#include <string>
Using namespace std;
Typedef struct tagStudentInfo
{
Int nID;
String strName;
}StudentInfo, *PStudentInfo; //学生信息
Classs sort
{
Public:
Bool operator() (StudentInfo const &_A, StudentInfo const &_B) const
{
If(_A.nID < _B.nID) return true;
If(_A.nID == _B.nID) return _A.strName.compare(_B.strName) < 0;
Return false;
}
};
Int main()
{
//用学生信息映射分数
Map<StudentInfo, int, sort>mapStudent;
StudentInfo studentInfo;
studentInfo.nID = 1;
studentInfo.strName = “student_one”;
mapStudent.insert(pair<StudentInfo, int>(studentInfo, 90));
studentInfo.nID = 2;
studentInfo.strName = “student_two”;
mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));
}
5. 另外
由于STL是一个统一的整体,map的很多用法都和STL中其它的东西结合在一起,比如在排序上,这里默认用的是小于号,即less<>,如果要从大到小排序呢,这里涉及到的东西很多,在此无法一一加以说明。
还要说明的是,map中由于它内部有序,由红黑树保证,因此很多函数执行的时间复杂度都是log2N的,如果用map函数可以实现的功能,而STL Algorithm也可以完成该功能,建议用map自带函数,效率高一些。
下面说下,map在空间上的特性,否则,估计你用起来会有时候表现的比较郁闷,由于map的每个数据对应红黑树上的一个节点,这个节点在不保存你的数据时,是占用16个字节的,一个父节点指针,左右孩子指针,还有一个枚举值(标示红黑的,相当于平衡二叉树中的平衡因子),我想大家应该知道,这些地方很费内存了吧,不说了……
6.
三种插入方式:
2.1.1用insert方法插入pair对象: enumMap.insert(pair<int, Cstring>(1, “One”)); 2.1.2 用insert方法插入value_type对象: enumMap.insert(map<int, Cstring>::value_type (1, “One”)); 2.1.3 用数组方式插入值: enumMap[1] = "One"; enumMap[2] = "Two"; ......这样非常直观,但存在一个性能的问题。插入2时,先在enumMap中查找主键为2的项,没发现,然后将一个新的对象插入enumMap,键是2,值是一个空字符串,插入完成后,将字符串赋为"Two"; 该方法会将每个值都赋为缺省值,然后再赋为显示的值,如果元素是类对象,则开销比较大。用前两种方法可以避免开销。
7.
从map中删除元素
移除某个map中某个条目用erase() 该成员方法的定义如下: 1.iterator erase(iterator it); //通过一个条目对象删除 2.iterator erase(iterator first, iterator last); //删除一个范围 3.size_type erase(const Key& key); //通过关键字删除 清除所有的元素clear() clear()就相当于 enumMap.erase(enumMap.begin(), enumMap.end());8.Map中的元素是自动按key升序排序,所以不能对map用sort函数
9.map的取值操作
map <string, int> word_count; // empty map
// insert default initialzed element with key Anna; then assign 1
to its value
word_count["Anna"] = 1;
将发生以下事情:
1). 在 word_count 中查找键为 Anna 的元素,没有找到。
2). 将一个新的键-值对插入到 word_count 中。它的键是 const string 类型
的对象,保存 Anna。而它的值则采用值初始化,这就意味着在本例中值为 0。
3). 将这个新的键-值对插入到 word_count 中。
4). 读取新插入的元素,并将它的值赋为 1。
使用下标访问 map 与使用下标访问数组或 vector 的行为截
然不同:用下标访问不存在的元素将导致在 map 容器中添加一
个新元素,它的键即为该下标值。
如同其他下标操作符一样,map 的下标也使用索引(其实就是键)来获取该
键所关联的值。如果该键已在容器中,则 map 的下标运算与 vector 的下标运
算行为相同:返回该键所关联的值。只有在所查找的键不存在时,map 容器才为
该键创建一个新的元素,并将它插入到此 map 对象中。此时,所关联的值采用
值初始化:类类型的元素用默认构造函数初始化,而内置类型的元素初始化为 0。