STL Associative Containers Types:map、set、multimap、mutilset以及对应的unordered类型

14 篇文章 3 订阅

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

关于map史上最详细使用方法说明,请点击:点击打开链接

http://blog.csdn.net/u010025211/article/details/46653675

八种容器的不同:

map:关联容器,保存键值对(key-value),不能有重复的键,有序,例如如果是string类型,则按字母表顺序

set:键即是值,没有pair

multimap:和map对应,区别是key可以重复出现多次

mutilset:和set对应,区别是key可以重复出现多次

unordered_map:map organised by a hash function,无序

unordered_set : set organised by a hash function,

unordered_multimap: Hased map; key can appear mutiple times;

unordered_mutiset: hashed set; key can appear mutiple times;

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!!!!!

如果不是用[],而是用insert插入,那么输出应为 2 3 1,map不能有重复键

 
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最大的区别。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值