map
Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性
map内部的实现自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能。
下面举例说明什么是一对一的数据映射。比如一个班级中,每个学生的学号跟他的姓名就存在着一一映射的关系,这个模型用map可能轻易描述,
很明显学号用int描述,姓名用字符串描述(本篇文章中不用char *来描述字符串,而是采用STL中string来描述),
下面给出map描述代码:
1.声明方式:
Map<int, string> mapStudent;
2.数据的插入
在构造map容器后,我们就可以往里面插入数据了。这里讲三种插入数据的方法:
第一种:用insert函数插入pair数据
Map<int, string> mapStudent;
mapStudent.insert(pair<int, string>(1, “student_one”));
第二种:用insert函数插入value_type数据
mapStudent.insert(map<int, string>::value_type (1, “student_one”));
第三种:用数组方式插入数据
mapStudent[1] = “student_one”;
3. map的大小
在往map里面插入了数据,我们怎么知道当前已经插入了多少数据呢,可以用size函数:
Int nSize = mapStudent.size();
4. 数据的遍历
第一种:应用前向迭代器
map<int, string>::iterator iter;
for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
Cout<<iter->first<<” ”<<iter->second<<end;
第二种:应用反相迭代器
map<int, string>::reverse_iterator iter;
for(iter = mapStudent.rbegin(); iter != mapStudent.rend(); iter++)
Cout<<iter->first<<” ”<<iter->second<<end;
第三种:用数组方式
int nSize = mapStudent.size()
for(int nIndex = 1; nIndex <= nSize; nIndex++)
Cout<<mapStudent[nIndex]<<end;
5.数据的查找(包括判定这个关键字是否在map中出现)
这里给出三种数据查找方法
第一种:用count函数来判定关键字是否出现,但是无法定位数据出现位置
第二种:用find函数来定位数据出现位置它返回的一个迭代器,
当数据出现时,它返回数据所在位置的迭代器,如果map中没有要查找的数据,它返回的迭代器等于end函数返回的迭代器
Int main()
{
Map<int, string> mapStudent;
mapStudent.insert(pair<int, string>(1, “student_one”));
mapStudent.insert(pair<int, string>(2, “student_two”));
mapStudent.insert(pair<int, string>(3, “student_three”));
map<int, string>::iterator iter;
iter = mapStudent.find(1);
if(iter != mapStudent.end())
{
Cout<<”Find, the value is ”<<iter->second<<endl;
}
Else
{
Cout<<”Do not Find”<<endl;
}
}
第三种:这个方法用来判定数据是否出现
Lower_bound函数用法,这个函数用来返回要查找关键字的下界(是一个迭代器)
Upper_bound函数用法,这个函数用来返回要查找关键字的上界(是一个迭代器)
例如:map中已经插入了1,2,3,4的话,如果lower_bound(2)的话,返回的2,而upper-bound(2)的话,返回的就是3
Equal_range函数返回一个pair,pair里面第一个变量是Lower_bound返回的迭代器,pair里面第二个迭代器是Upper_bound返回的迭代器,如果这两个迭代器相等的话,则说明map中不出现这个关键字,程序说明
mapPair = mapStudent.equal_range(2);
if(mapPair.first == mapPair.second)
cout<<”Do not Find”<<endl;
6.数据的清空与判空
清空map中的数据可以用clear()函数,判定map中是否有数据可以用empty()函数,它返回true则说明是空map
7.数据的删除
这里要用到erase函数,它有三个重载了的函数
迭代器删除
iter = mapStudent.find(1);
mapStudent.erase(iter);
用关键字删除
Int n = mapStudent.erase(1);//如果删除了会返回1,否则返回0
用迭代器,成片的删除
一下代码把整个map清空
mapStudent.earse(mapStudent.begin(), mapStudent.end());
//成片删除要注意的是,也是STL的特性,删除区间是一个前闭后开的集合
#include <stdio.h>
#include <string>
#include <stdlib.h>
#include <iostream>
#include <map>
#include <vector>
using namespace std;
typedef map<int, string> STRtemplatemap;
int main()
{
STRtemplatemap Student;
Student.insert(pair<int, string>(1, "student_one"));
Student[2]="student_two";
Student.insert(STRtemplatemap::value_type (3, "student_three"));
for(STRtemplatemap::iterator iter=Student.begin();iter!=Student.end();iter++)
cout << iter->second << endl;
getchar();
return 0;
}
8.其他一些函数用法
这里有swap,key_comp,value_comp,get_allocator等函数,有兴趣的话可以自个研究
简单例子:
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <map>
using namespace std;
typedef map <int ,string> templatemap;
templatemap testmap;
void main()
{
string data2="getid()";
string data1="gethp()";
string data="getmp()";
testmap[1]=data;
testmap[2]=data1;
testmap[3]=data2;
for (templatemap::iterator iter = testmap.begin();iter != testmap.end(); iter++)
{
cout<<iter->first<<" ";
string data2=iter->second;
for(int i=0;i<strlen(data2.c_str());i++)
{
cout<<data2[i];
}
cout<<endl;
}
templatemap::iterator itr = testmap.find(3);
if(itr == testmap.end())
return;
string data4 = itr->second;
cout<<3<<" ";
for(int i=0;i<strlen(data4.c_str());i++)
{
cout<<data4[i];
}
cout<<endl;
system("pause");
}
map 装struct
#include <vector>
#include <iostream>
#include <map>
using namespace std;
struct Activity
{
int m_nStep;
int m_nCount;
Activity():
m_nStep(1),m_nCount(0)
{
}
Activity(const int nStep,const int nCount):
m_nStep(nStep),m_nCount(nCount)
{
}
};
int main()
{
map <int ,Activity> test;
test[1001] = Activity(1,10);
cout<<"ID:"<<1001<<"步骤:"<<test[1001].m_nStep<<"人数:"<<test[1001].m_nCount<<endl;
system("pause");
return 0;
}
map最好不要在使用的时候删除东西
#include <iostream>
#include <map>
using namespace std;
typedef map<int, int> templatemap;
templatemap AllScoreSort;
void main()
{
for(int i=10000;i<10010;i++)
AllScoreSort[i]=i;
for (templatemap::iterator iter = AllScoreSort.begin(); iter!= AllScoreSort.end(); iter++)
{
int nRoleID = iter->first;
int nScore = iter->second;
if (10005 < nRoleID)
{
//AllScoreSort.erase(nRoleID); //注意这行
continue;
}
cout<<nRoleID<<" "<<nScore<<endl;
}
system("pause");
}
struct vector map嵌套使用
#include <iostream>
#include <vector>
#include <map>
using namespace std;
struct LevelAwardItems
{
int m_ItemID;
int m_Num;
int m_KeyWorld;
};
typedef vector<LevelAwardItems> templateItem;
templateItem m_VectItem;
map <int, templateItem>m_MapLevelAward;
void main()
{
for(int j=0;j<2;j++)
{
for(int i=0;i<2;i++)
{
LevelAwardItems item;
item.m_ItemID = i;
item.m_Num = i;
item.m_KeyWorld = i;
m_VectItem.push_back(item);
}
m_MapLevelAward[j] = m_VectItem;
m_VectItem.clear();
}
for(int j = 0;j<2;j++)
{
m_VectItem = m_MapLevelAward[j];
int nItemCout = m_VectItem.size();
for(int k = 0;k <nItemCout;k++)
{
LevelAwardItems item;
item = m_VectItem[k];
cout<<item.m_ItemID<<endl;
cout<<item.m_Num<<endl;
cout<<item.m_KeyWorld<<endl;
}
}
system("pause");
}
map map 嵌套使用
#include<map>
#include<iostream>
#include <string>
using namespace std;
int main()
{
map<int,map<int,string> >multiMap; //对于这样的map嵌套定义,
map<int, string> temp; //定义一个map<int, string>变量,对其定义后在插入multiMap
temp[90] = "hi";
temp[100] = "maxi";
multiMap[10] = temp;
multiMap[10][80]="xiaoyu";
multiMap[5][30]="xiaoma";
map<int,map<int,string> >::iterator multitr; // 以下是如何遍历本multiMap
map<int,string>::iterator intertr;
for(multitr=multiMap.begin();multitr!=multiMap.end();multitr++)
{
for(intertr= multitr ->second.begin(); intertr != multitr ->second.end(); intertr ++)
cout<< multitr ->first<<" "<<intertr->first<<" ("<<intertr -> second <<")"<<endl;
}
system("pause");
return 0;
}
stl之map erase方法的正确使用STL的map表里有一个erase方法用来从一个map中删除掉指令的节点
eg:
map<string,string> mapTest;
typedef map<string,string>::iterator ITER;
ITER iter=mapTest.find(key);
mapTest.erase(iter);
像上面这样只是删除单个节点,map的形为不会出现任务问题,
但是当在一个循环里用的时候,往往会被误用,那是因为使用者没有正确理解iterator的概念.
像下面这样的一个例子就是错误的写法,
eg.
for(ITER iter=mapTest.begin();iter!=mapTest.end();++iter)
{
cout<<iter->first<<":"<<iter->second<<endl;
mapTest.erase(iter);
}
这是一种错误的写法,会导致程序行为不可知.究其原因是map 是关联容器,对于关联容器来说,如果某一个元素已经被删除,那么其对应的迭代器就失效了,不应该再被使用;否则会导致程序无定义的行为。
可以用以下方法解决这问题:
正确的写法
1.使用删除之前的迭代器定位下一个元素。STL建议的使用方式
for(ITER iter=mapTest.begin();iter!=mapTest.end();)
{
cout<<iter->first<<":"<<iter->second<<endl;
mapTest.erase(iter++);
}
2. erase() 成员函数返回下一个元素的迭代器
for(ITER iter=mapTest.begin();iter!=mapTest.end();)
{
cout<<iter->first<<":"<<iter->second<<endl;
iter=mapTest.erase(iter);
}
注意:
map的earse应注意:
map这种容器的下边访问和Vector等容器的下标访问有本质的区别。
对于Vector容器,用aVector[i]访问第i个元素时,如果元素不存在,容器不会增加元素,
而对于map,用aMap[key]
访问键key对应的对象时,如果该键对应的对象存在,则返回该对象(这和Vector一样),但是,当键值为key的元素不存在时,容器会自动的增加一个pair,键为key,而值则为一个容器定义时指定的类型并默认初始化(即,如果该类型为基本类型,则初始化为0,比如本例中,aMap[1]的使用会产生一个pair,<1,NULL>,若该类型为类类型,则调用默认构造函数初始化之)
显然,本例中,aMap[1]为NULL,后面的erase()不会执行,使得后面的
插入语句aMap.insert(1,new A())键值冲突
eg:如下代码会导致错误
#include <iostream>
#include <map>
using namespace std;
struct A
{
A(int i)
{
x=i;
}
int x;
};
int main()
{
map<int,A*> amap;
if ( amap[1] != NULL )
amap.erase(1);
amap.insert(make_pair(1,new A(1)));
amap.insert(make_pair(2,new A(2)));
amap.insert(make_pair(3,new A(3)));
return 0;
}
#include <string>
#include <iostream>
#include <map>
using namespace std;
class A
{
public:
A(int _x,int _y)
{
x =_x;
y =_y;
}
int x;
int y;
};
typedef map<string,A*> stringAMap;
int main()
{
stringAMap map1;
A* a = new A(100,200);
map1.insert(make_pair("韦宇浩",a));
map1.insert(make_pair("陆一峰",new A(200,300)));
stringAMap::iterator pos = map1.find("韦宇浩");
if (pos != map1.end())
{
//delete(pos->second);
map1.erase(pos);
}
cout << a->x<<endl;
system("pause");
return 0;
}
stl map高效遍历删除的方法
for(;iter!=mapStudent.end();)
{
if((iter->second)>=aa)
{
//满足删除条件,删除当前结点,并指向下面一个结点
mapStudent.erase(iter++);
}
else
{
//条件不满足,指向下面一个结点
iter++;
}
}
点击打开链接