map详解

来源:互联网 发布:网络协议服务 编辑:程序博客网 时间:2024/05/16 07:54
Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。这里说下map内部数据的组织,map内部自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处。
  1. map的构造函数
  map<int, string> maphai;
  map<char,int> maphai;
  map<string,char> mapstring;
  map<string,int> mapstring;
  map<int ,char>mapint;
  map<char,string>mapchar;
  2. 数据的插入
  在构造map容器后,我们就可以往里面插入数据了。这里讲三种插入数据的方法:
  第一种:用insert函数插入pair数据,
  #include <map>
  #include <string>
  #include <iostream>
  Using namespace std;
  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;
  for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
  {
  Cout<<iter->first<<” ”<<iter->second<<end;
  }
  }
  第二种:用insert函数插入value_type数据,下面举例说明
  #include <map>
  #include <string>
  #include <iostream>
  Using namespace std;
  Int main()
  {
  Map<int, string> mapStudent;
  mapStudent.insert(map<int, string>::value_type (1, “student_one”));
  mapStudent.insert(map<int, string>::value_type (2, “student_two”));
  mapStudent.insert(map<int, string>::value_type (3, “student_three”));
  map<int, string>::iterator iter;
  for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
  {
  Cout<<iter->first<<” ”<<iter->second<<end;
  }
  }
  第三种:用数组方式插入数据,下面举例说明
  #include <map>
  #include <string>
  #include <iostream>
  Using namespace std;
  Int main()
  {
  Map<int, string> mapStudent;
  mapStudent[1] = “student_one”;
  mapStudent[2] = “student_two”;
  mapStudent[3] = “student_three”;
  map<int, string>::iterator iter;
  for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
  {
  Cout<<iter->first<<” ”<<iter->second<<end;
  }
  }
  以上三种用法,虽然都可以实现数据的插入,但是它们是有区别的,当然了第一种和第二种在效果上是完成一样的,用insert函数插入数据,在数据的插入上涉及到集合的唯一性这个概念,即当map中有这个关键字时,insert操作是插入数据不了的,但是用数组方式就不同了,它可以覆盖以前该关键字对应的值,用程序说明
  mapStudent.insert(map<int, string>::value_type (1, “student_one”));
  mapStudent.insert(map<int, string>::value_type (1, “student_two”));
  上面这两条语句执行后,map中1这个关键字对应的值是“student_one”,第二条语句并没有生效,那么这就涉及到我们怎么知道insert语句是否插入成功的问题了,可以用pair来获得是否插入成功,程序如下
  Pair<map<int, string>::iterator, bool> Insert_Pair;
  Insert_Pair = mapStudent.insert(map<int, string>::value_type (1, “student_one”));
  我们通过pair的第二个变量来知道是否插入成功,它的第一个变量返回的是一个map的迭代器,如果插入成功的话Insert_Pair.second应该是true的,否则为false。
  下面给出完成代码,演示插入成功与否问题
  #include <map>
  #include <string>
  #include <iostream>
  Using namespace std;
  Int main()
  {
  Map<int, string> mapStudent;
  Pair<map<int, string>::iterator, bool> Insert_Pair;
  Insert_Pair = mapStudent.insert(pair<int, string>(1, “student_one”));
  If(Insert_Pair.second == true)
  {
  Cout<<”Insert Successfully”<<endl;
  }
  Else
  {
  Cout<<”Insert Failure”<<endl;
  }
  Insert_Pair = mapStudent.insert(pair<int, string>(1, “student_two”));
  If(Insert_Pair.second == true)
  {
  Cout<<”Insert Successfully”<<endl;
  }
  Else
  {
  Cout<<”Insert Failure”<<endl;
  }
  map<int, string>::iterator iter;
  for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
  {
  Cout<<iter->first<<” ”<<iter->second<<end;
  }
  }
  大家可以用如下程序,看下用数组插入在数据覆盖上的效果
  #include <map>
  #include <string>
  #include <iostream>
  Using namespace std;
  Int main()
  {
  Map<int, string> mapStudent;
  mapStudent[1] = “student_one”;
  mapStudent[1] = “student_two”;
  mapStudent[2] = “student_three”;
  map<int, string>::iterator iter;
  for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
  {
  Cout<<iter->first<<” ”<<iter->second<<end;
  }
  }
  3. map的大小
  在往map里面插入了数据,我们怎么知道当前已经插入了多少数据呢,可以用size函数,用法如下:
  Int nSize = mapStudent.size();
  4. 数据的遍历
  这里也提供三种方法,对map进行遍历
  第一种:应用前向迭代器,上面举例程序中到处都是了,略过不表
  第二种:应用反相迭代器,下面举例说明,要体会效果,请自个动手运行程序
  #include <map>
  #include <string>
  #include <iostream>
  Using namespace std;
  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>::reverse_iterator iter;
  for(iter = mapStudent.rbegin(); iter != mapStudent.rend(); iter++)
  {
  Cout<<iter->first<<” ”<<iter->second<<end;
  }
  }
  第三种:用数组方式,程序说明如下
  #include <map>
  #include <string>
  #include <iostream>
  Using namespace std;
  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”));
  int nSize = mapStudent.size()
  //此处有误,应该是 for(int nIndex = 1; nIndex <= nSize; nIndex++)
  //by rainfish
  for(int nIndex = 0; nIndex < nSize; nIndex++)
  {
  Cout<<mapStudent[nIndex]<<end;
  }
  }
  5. 数据的查找(包括判定这个关键字是否在map中出现)
  在这里我们将体会,map在数据插入时保证有序的好处。
  要判定一个数据(关键字)是否在map中出现的方法比较多,这里标题虽然是数据的查找,在这里将穿插着大量的map基本用法。
  这里给出三种数据查找方法
  第一种:用count函数来判定关键字是否出现,其缺点是无法定位数据出现位置,由于map的特性,一对一的映射关系,就决定了count函数的返回值只有两个,要么是0,要么是1,出现的情况,当然是返回1了
  第二种:用find函数来定位数据出现位置,它返回的一个迭代器,当数据出现时,它返回数据所在位置的迭代器,如果map中没有要查找的数据,它返回的迭代器等于end函数返回的迭代器,程序说明
  #include <map>
  #include <string>
  #include <iostream>
  Using namespace std;
  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中不出现这个关键字,程序说明
  #include <map>
  #include <string>
  #include <iostream>
  Using namespace std;
  Int main()
  {
  Map<int, string> mapStudent;
  mapStudent[1] = “student_one”;
  mapStudent[3] = “student_three”;
  mapStudent[5] = “student_five”;
  map<int, string>::iterator iter;
  iter = mapStudent.lower_bound(2);
  {
  //返回的是下界3的迭代器
  Cout<<iter->second<<endl;
  }
  iter = mapStudent.lower_bound(3);
  {
  //返回的是下界3的迭代器
  Cout<<iter->second<<endl;
  }
  iter = mapStudent.upper_bound(2);
  {
  //返回的是上界3的迭代器
  Cout<<iter->second<<endl;
  }
  iter = mapStudent.upper_bound(3);
  {
  //返回的是上界5的迭代器
  Cout<<iter->second<<endl;
  }
  Pair<map<int, string>::iterator, map<int, string>::iterator> mapPair;
  mapPair = mapStudent.equal_range(2);
  if(mapPair.first == mapPair.second)
  {
  cout<<”Do not Find”<<endl;
  }
  Else
  {
  Cout<<”Find”<<endl;
  }
  mapPair = mapStudent.equal_range(3);
  if(mapPair.first == mapPair.second)
  {
  cout<<”Do not Find”<<endl;
  }
  Else
  {
  Cout<<”Find”<<endl;
  }
  }
  6. 数据的清空与判空
  清空map中的数据可以用clear()函数,判定map中是否有数据可以用empty()函数,它返回true则说明是空map
  7. 数据的删除
  这里要用到erase函数,它有三个重载了的函数,下面在例子中详细说明它们的用法
  #include <map>
  #include <string>
  #include <iostream>
  Using namespace std;
  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”));
  //如果你要演示输出效果,请选择以下的一种,你看到的效果会比较好
  //如果要删除1,用迭代器删除
  map<int, string>::iterator iter;
  iter = mapStudent.find(1);
  mapStudent.erase(iter);
  //如果要删除1,用关键字删除
  Int n = mapStudent.erase(1);//如果删除了会返回1,否则返回0
  //用迭代器,成片的删除
  //一下代码把整个map清空
  mapStudent.earse(mapStudent.begin(), mapStudent.end());
  //成片删除要注意的是,也是STL的特性,删除区间是一个前闭后开的集合
  //自个加上遍历代码,打印输出吧
  }
  8. 其他一些函数用法
  这里有swap,key_comp,value_comp,get_allocator等函数,感觉到这些函数在编程用的不是很多,略过不表,有兴趣的话可以自个研究
  9. 排序
  这里要讲的是一点比较高深的用法了,排序问题,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));
  }
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 2岁半的宝宝说话结巴怎么办 2周3宝宝不会说话胆小怎么办 宝宝我2岁多了说话有点结巴怎么办 两岁宝宝说话突然结巴了怎么办 两岁3宝宝叫她名字不理人怎么办 九个月的宝宝身高不达标怎么办 3岁宝宝又吐又拉怎么办 宝宝发烧39度怎么办手脚很烫 两岁宝宝吃什么吐什么怎么办 7岁宝宝吃多了吐怎么办 7个月的宝宝大便干燥怎么办 10个月宝宝便秘大便干燥怎么办 一岁半宝宝老是拉糊糊状大便怎么办 外阴部长了一个疙瘩有点痒怎么办 小孩打架被另一个小孩家人告怎么办 德保豆浆机有电但不工作怎么办 刚买的笔记本c盘不足怎么办 qq糖粘在喉咙气管里怎么办 穿上旗袍后感觉后腰处不平整怎么办 机打票给客人给错联怎么办?急 ps修证件照感觉不太立体怎么办 手机百度上下载的文档打不开怎么办 5岁宝宝乘飞机没带证件怎么办 网上订飞机票忘记订儿童票了怎么办 两岁宝宝对牛奶鸡蛋过敏了怎么办 两岁宝宝坐不住好跑怎么办 宝宝两岁多了不愿意坐小马桶怎么办 坐火车小孩拉屎在被子上怎么办 川航飞机票名字错了一个字怎么办 胜战本领怎么看走向战场怎么办 数数字油画你的颜料干了怎么办? 数字油画涂颜料涂错了怎么办 绝地求生模拟器注册已达上限怎么办 孕妇把番茄和虾一起吃了怎么办 4岁宝贝吃了玩具小电池怎么办 微信使用零钱需完善实名信息怎么办 两岁宝宝刷牙不会吐水怎么办 孩子牙龈上长了小牙怎么办 供暖公司未供暖却收取供暖费怎么办 两岁宝宝认知和语言能力低怎么办 蜡笔同步被对方发现删掉的怎么办