详解map、multimap、unordered_map、unordered_multimap

详解map、multimap、unordered_map、unordered_multimap

相信有不少同学和我一样刚接触C++ STL,被其深深吸引。但是想弄懂每个模板类不是一个容易事。大家应该对vector、list、stack、queue等类比较了解了,所以今天详细介绍下几个很常用很强大但有点不太好懂的类map、multimap、unordered_map、unordered_multimap。乍一看都差不多都是什么map,但这肯定有所不同。下面就在一个一个讲解的同时,让大家了解这四个类的使用,以及不同之处。

map

1)  从一个简单的例子开始


2)      #include<map>

3)      #include<iostream>

4)      using namespace std;

5)

6)      int main()

7)      {

8)          map<char,int> msi;

9)          //map::operator[]

10)      msi[‘x‘] = 3;

11)      msi[‘z‘] = 3;

12)      msi[‘g‘] = 2;

13)      msi[‘y‘] = 1;

14)      //map::at()

15)      auto beg = msi.begin();

16)      for(; beg !=msi.end();beg++){

17)          cout<<msi.at(beg->first)<<" ";

18)      }

19)      cout<<endl;

20)      return 1;

21)  }

结果:

2 3 1 3

代码分析:

l map::operator[]

mapped_type& operator[] (const key_type& k);
mapped_type& operator[] (key_type&& k);

该函数通过调用mak_pair函数将k,v作为一个kv对,在通过insert函数按照k将v插入map中。

l map::at

mapped_type& at (const key_type& k);
const mapped_type& at (const key_type& k) const;
该函数通过k来找到v值。
l  从结果看出,打印是按照k值递增来打印v值的。

2) 从例子1)继续

我们对例子1中的代码进行下修改。


1)      #include<map>

2)      #include<iostream>

3)      using namespace std;

4)

5)      int main()

6)      {

7)          map<char,int> msi;

8)          //map::operator[]

9)          msi[‘x‘] = 3;

10)      msi[‘x‘] = 4;  //这里修改了

11)      msi[‘g‘] = 2;

12)      msi[‘y‘] = 1;

13)      //map::at()

14)      auto beg = msi.begin();

15)      for(; beg !=msi.end();beg++){

16)          cout<<msi.at(beg->first)<<" ";

17)      }

18)      cout<<endl;

19)      return 1;

20)  }

结果:

2 4 1

代码分析:

l 这里出现了重复key值x,那么是不是x/3对就被覆盖了呢????因此只打印出2 41!!!!!

 

3) 从例子2)继续


1)      int main()

2)      {

3)          map<char,int> msi;

4)          //map::operator[]

5)          msi[‘x‘] = 3;

6)          msi[‘x‘] = 4;

7)          msi[‘g‘] = 2;

8)          msi[‘y‘] = 1;

9)          //map::at()

10)      auto beg = msi.begin();

11)      for(; beg !=msi.end();beg++){

12)          cout<<msi.at(beg->first)<<" ";

13)      }

14)      cout<<endl;

15)

16)      auto get = msi.equal_range(‘x‘);

17)      auto skbeg = get.first;

18)      auto skend = get.second;

19)      for(; skbeg!=skend; skbeg++){

20)          cout<<skbeg->first<<":"<<skbeg->second<<" ";

21)      }

22)      cout<<endl;

23)

24)      return 1;

25)  }

结果:

2 4 1

x:4

代码分析:

l map::equal_range

pair<const_iterator,const_iterator> equal_range (const key_type& k) const;
pair<iterator,iterator>             equal_range (const key_type& k);

按照reference中的意思这个函数应该是返回包含k的element的上下界,但是我们并没有打印出,x:3 x:4。所以呢,嗯我们得出一个结论在map中k和v是一对一的关系,不能出现一个k对应多个v值的情况。

4) OK继续


1)      int main()

2)      {

3)          map<char,int> msi;

4)          //map::operator[]

5)          msi[‘c‘] = 3;

6)          msi[‘h‘] = 5;

7)          msi[‘b‘] = 2;

8)          msi[‘a‘] = 1;

9)

10)      //insert g

11)      msi.insert(pair<char,int>(‘g‘,4));

12)      //copy map

13)      map<char,int> newmap;

14)      newmap.insert(msi.begin(), msi.find(‘g‘));

15)      //map::at()

16)      auto beg = msi.begin();

17)      for(; beg !=msi.end();beg++){

18)          cout<<beg->first<<"->"<<msi.at(beg->first)<<" ";

19)      }

20)      cout<<endl;

21)

22)      auto newbeg = newmap.begin();

23)      for(; newbeg !=newmap.end();newbeg++)

24)          cout<<newbeg->first<<"->"<<newmap.at(newbeg->first)<<" ";

25)      cout<<endl;

26)      /*auto get = msi.equal_range(‘x‘);

27)      auto skbeg = get.first;

28)      auto skend = get.second;

29)      for(; skbeg!=skend; skbeg++){

30)          cout<<skbeg->first<<":"<<skbeg->second<<" ";

31)      }*/

32)

33)      cout<<endl;

34)

35)      return 1;

36)  }

结果:

a->1 b->2 c->3 g->4 h->5

a->1 b->2 c->3

代码分析:

l map::insert

template <class P> pair<iterator,bool> insert (P&& val);
template <class InputIterator>
void insert (InputIterator first, InputIterator last);

这里分别使用了这两种insert函数,其中第一个我们将一个pair对象作为一个element存入map;第二个我们将msi中从开始到g以前的element存入了newmap中。

4) TBC

还有些没有介绍到的成员函数,我想就在另外几个类中介绍吧,其实都很简单…

multimap

1)    直奔主题


1)      #include<map>

2)      #include<iostream>

3)      #include<string>

4)      using namespace std;

5)

6)      bool cmp(const string &a, const string &b)

7)      {

8)          return a.compare(b)>0?true:false;

9)      }

10)

11)  int main()

12)  {

13)      bool (*cmp_pt) (const string&, const string&) = cmp;

14)      multimap<string, int, bool(*) (const string&, const string&)> mci(cmp_pt); //降序

15)      mci.insert(pair<string,int>("bb",2));

16)      mci.insert(pair<string,int>("aa",1));

17)      mci.insert(pair<string,int>("cc",3));

18)      mci.insert(pair<string,int>("gg",6));

19)      mci.insert(pair<string,int>("cc",5));//重复

20)

21)      auto beg = mci.begin();

22)      for(;beg!=mci.end();beg++){

23)          cout<<beg->first<<"->"<<beg->second<<" ";

24)      }

25)      cout<<endl;

26)      auto skget = mci.equal_range("cc");

27)      auto skbeg = skget.first;

28)      auto skend = skget.second;

29)      for(;skbeg!=skend;skbeg++ )

30)          cout<<skbeg->first<<"->"<<skbeg->second<<" ";

31)      cout<<endl;

32)  }

结果:

gg->6 cc->3 cc->5 bb->2 aa->1

cc->3 cc->5

代码分析:

l 降序输出

这里有两种方法,一种是函数指针,一种是类。这里采用的前者。类方法更加简单,只需要重载operator()即可,如下所示。


struct classcomp {

  bool operator() (const
char& lhs, const char& rhs)
const

  {return lhs<rhs;}

};


std::multimap<char,int,classcomp> fourth;

l 初始化数据

数据不能通过operator[]给予喽~,没这个成员函数。

l  重点来了

可以发现尽管加入了重复键值cc/5,但是打印的时候我们依然输出了重复的键值对,因此我们可以说multimap和map的一个最大的区别就是,multimap可以实现一对多的存储方式!!!!!!!!

unordered_multimap

1)  依然直奔主题


1)      #include<iostream>

2)      #include<unordered_map>

3)      using namespace std;

4)

5)      int main()

6)      {

7)          unordered_multimap<char,int> umci,insertum={ {‘b‘,12},{‘w‘,11} };

8)          umci.insert(make_pair(‘d‘,5));

9)          umci.insert(pair<char,int>(‘a‘,1));

10)      umci.insert(make_pair(‘b‘,2));

11)      umci.insert(make_pair(‘g‘,8));

12)      umci.insert(insertum.begin(),insertum.end());

13)

14)      auto beg = umci.begin();

15)      for(;beg!=umci.end();beg++)

16)          cout<<beg->first<<"->"<<beg->second<<" ";

17)      cout<<endl;

18)

19)      return 1;

20)  }

结果:

g->8 b->12 b->2 w->11 a->1 d->5

代码分析:

l  无序存储

可以明显的看出unordered_multimap的无序存储特点,这是其与multimap最大的区别。

时间: 2024-10-10 23:12:21

详解map、multimap、unordered_map、unordered_multimap的相关文章

【python】详解map函数的用法之函数并行作用解析

Python函数编程中的map(func, seq1[, seq2,-]) 函数是将func作用于seq中的每一个元素,其中seq须是可迭代对象,并将所有的调用的结果作为一个list返回.如果func为None,作用同zip(). 本文参考自:Python中map()函数浅析一文,感谢精彩分享. 下面举得例子来帮助我们更好的理解这个工作过程: 1.对可迭代函数'iterable'中的每一个元素应用'function'方法,将结果作为list返回. 2.如果给出了额外的可迭代参数,则对每个可迭代参

java如何对map进行排序详解(map集合的使用)

今天做统计时需要对X轴的地区按照地区代码(areaCode)进行排序,由于在构建XMLData使用的map来进行数据统计的,所以在统计过程中就需要对map进行排序. 一.简单介绍Map 在讲解Map排序之前,我们先来稍微了解下map.map是键值对的集合接口,它的实现类主要包括:HashMap,TreeMap,Hashtable以及LinkedHashMap等.其中这四者的区别如下(简单介绍): HashMap:我们最常用的Map,它根据key的HashCode 值来存储数据,根据key可以直接

详解 集合框架

我们对于数据的存储,在不同场合有不同的需求,而对于这些需求,Java给出了一个框架 -- 集合框架 集合框架: 集合的由来 : 面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,Java就提供了集合类. 数组和集合的区别 (1): 长度区别: 数组的长度是固定的 而集合的长度是可变的 (2): 存储数据类型的区别: 数组可以存储基本数据类型 , 也可以存储引用数据类型; 而集合只能存储引用数据类型 (3): 内容区别: 数组只能存储同种数据类型的元素 , 集合可以存储不同类

STL之六:map/multimap用法详解

转载于:http://blog.csdn.net/longshengguoji/article/details/8547007 map/multimap 使用map/multimap之前要加入头文件#include<map>,map和multimap将key/value当作元素,进行管理.它们可根据key的排序准则自动将元素排序.multimap允许重复元素,map不允许重复元素. map和multimap内部的数据结构也是平衡二叉树. map和multimap根据元素的key自动对元素进行排

Cocos2d-x3.0模版容器详解之——cocos2d::Vector&lt;T&gt;, cocos2d::Map&lt;K,V&gt;, cocos2d::Value

Cocos2d-x3.0模版容器详解之一:cocos2d::Vector<T>  http://www.cocoachina.com/bbs/read.php?tid=199793Cocos2d-x3.0模版容器详解之二:cocos2d::Map<K,V>  http://www.cocoachina.com/bbs/read.php?tid=199916Cocos2d-x3.0模版容器详解之三:cocos2d::Value  http://www.cocoachina.com/b

源映射(Source Map)详解

一.什么是源映射 为了提高性能,很多站点都会先压缩 JavaScript 代码然后上线, 但如果代码运行时出现错误,浏览器只会显示在已压缩的代码中的位置,很难确定真正的源码错误位置. 这时源映射就登场了. 源映射(Source Map)是一种数据格式,它存储了源代码和生成代码之间的位置映射关系. 源映射一般使用 .map 扩展名,源映射本质是一个 JSON 文本文档,其 MIME 类型也一般设为 application/json. 二.如何使用源映射 在 JavaScript 代码中添加注释:

STL之map容器的详解

一.关于map的介绍 map是STL的 一个容器,和set一样,map也是一种关联式容器.它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键 字的值)的数据处理能力,由于这个特性,有助于我们处理一对一数据.这里说下map内部数据的组织,map内部是自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的.学习map我们一定要理解什么是一对一的数据映射?比如:一个班级中,每个学生的学号跟他的姓名

技术分享:html中的Map,area标签详解

area标签详解 一.界说和用法 html中的Map.> 界说一个客户端图画映射.图画映射(image-map指带有可点击区域的一幅图画. 二.脚本示例: shqpe特点的设置阐明0.: 1.rect界说一个矩形区域.右下角的坐标,coord特点设置值为矩形的左上角.各个坐标值之间用逗号分隔; coord特点设置值为多边形各项极点的坐标值2.poli界说一个多边形区域.; 3.circl界说一格圆形区域.前两个参数分别为圆心的横,coord特点设置值为圆心坐标及半径.纵坐标,第三个参数为半径.

hadoop学习WordCount+Block+Split+Shuffle+Map+Reduce技术详解

转自:http://blog.csdn.net/yczws1/article/details/21899007 纯干货:通过WourdCount程序示例:详细讲解MapReduce之Block+Split+Shuffle+Map+Reduce的区别及数据处理流程. Shuffle过程是MapReduce的核心,集中了MR过程最关键的部分.要想了解MR,Shuffle是必须要理解的.了解Shuffle的过程,更有利于我们在对MapReduce job性能调优的工作有帮助,以及进一步加深我们对MR内