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++;
     }
}
点击打开链接

 

posted @ 2011-10-18 17:35  byfei  阅读(46)  评论(0编辑  收藏  举报