map 和set

链接https://blog.csdn.net/payshent/article/details/55223099

关于容器我们知道的在STL中有关联容器和顺序容器,那么所谓的关联容器是什么?所谓的顺序容器又是什么呢?在STL中的哪些属于关联容器,哪些属于顺序容器呢?下面来做一个简单的介绍:关联容器中的元素是按照关键字来保存和访问的,C++中的关联容器重要就是map和set。而顺序容器是按照元素在容器中的位置来进行保存和访问的,在C++中的顺序容器是Vector、List、Deque。今天我就关联容器来给大家做一个简单的介绍。  

一、set(集合)  

set是一种key结构,set是能够存储同一数据类型的数据结构,经过存入set的数据会自动的进行排序,set的底层是用红黑树来进行实现的。

1、插入:insert()

1)pair<iterator,bool> insert ( const value_type& x )

在迭代器中插入一个数据,如果这个数据不存在就直接插入,其返回值为插入后元素的迭代器和true。如果这个元素已经存在,那么返回当前元素以及false.

在这里补充一下pair,pair是一种模板模型,每个pair可以存储两个值,这俩个值得类型是任意类型。定义在#include<utility>中,其标准形式为:template<class T1,class T2> struct pair;

 
  1. template <class T1, class T2> struct pair

  2. {

  3. typedef T1 first_type;

  4. typedef T2 second_type;

  5.  
  6. T1 first;

  7. T2 second;

  8. pair() : first(T1()), second(T2()) {}

  9. pair(const T1& x, const T2& y) : first(x), second(y) {}

  10. template <class U, class V>

  11. pair (const pair<U,V> &p) : first(p.first), second(p.second) { }

  12. }

 pair<iterator,bool> insert(const value_type& x)

我们可以看到pair有两个成员分别是first和second,set是一个模板,first是一个指向要插入位置的迭代器,如果second是false则first就是已经存在的元素的这个位置的迭代器,如果second为true,first就是要插入位置的迭代器。

2)iterator insert ( iterator position, const value_type& x )

在指定的位置插入指定的数据,position是一个迭代器的位置,x表示的是要插入的数。如果插入成功的话,会返回一个插入新位置的迭代器。

2)template<class InputIterator> void insert(InputIterator first,InputIterator last)

插入一段迭代器区间

2、删除(erase)

1)void erase(iterator position)

删除一个迭代器位置

2)size_type erase(sonst key_type& x)

删除成功的话就返回1

3)void erase(iterator first, iterator last)

删除一段迭代器区间

3、查找:find()

iterator find(const key_type& x) const;

若找到返回该迭代器的位置,否则就返回的是最后一个元素后面的位置

4、数量:count()

size_type count(const key_type& x)const

count是为了统计某个数值出现的次数,在set里面不能重复出现相同的数值,count的返回值只有0和1两个值,0表示的是不存在,1表示存在。

关于set的用法我将通过下面的代码展示来给大家做一个进一步的说明

 
  1. #include<iostream>

  2. using namespace std;

  3. #include<set>

  4. void fun(set<int> myset)

  5. {

  6. set<int>::iterator it;

  7. for (it=myset.begin(); it!=myset.end(); it++)

  8. {

  9. cout <<*it<<" ";

  10. }

  11. cout << endl;

  12.  
  13. }

  14. void TestSet()

  15. {

  16. set<int> t;

  17. set<int>::iterator it;

  18. pair<set<int>::iterator,bool> ret;

  19. t.insert(1);

  20. t.insert(2);

  21. t.insert(3);

  22. t.insert(4);

  23. t.insert(5);

  24. fun(t);

  25. cout<<endl;

  26.  
  27. ret = t.insert(2);

  28. if(ret.second == false)

  29. {

  30. it=ret.first;

  31. }

  32. cout<<*it<<endl;

  33. //第二种插入

  34. t.insert (it,7);

  35. t.insert (it,8);

  36. t.insert (it,9);

  37. fun(t);

  38. cout<<endl;

  39. //第三种插入

  40. int a[]= {1,11,111};

  41. t.insert (a,a+3);

  42. fun(t);

  43. cout<<endl;

  44. cout<<"1 count:"<<t.count(10)<<endl;

  45. cout<<"size:"<<t.size()<<endl;

  46.  
  47. t.erase (1);

  48. fun(t);

  49. cout<<endl;

  50.  
  51. it=t.begin();

  52. it++;

  53. t.erase (it);

  54. fun(t);

  55. cout<<endl;

  56. it=t.find (11);

  57. t.erase ( it, t.end() );

  58. fun(t);

  59. cout<<endl;

  60. }

  61.  
  62. int main()

  63. {

  64. TestSet();

  65. return 0;

  66. }

程序的输出结果是:


二、map(映射)

有别于set的是,map是一种key(键),value(值)的形式,用来保存键和值组成的集合,键必须是唯一的,但值可以不唯一。里面的元素可以根据键进行自动排序,由于map是key_value的形式,所以map里的所有元素都是pair类型。pair里面的first被称为key(键),second被称为value(值)。map的底层是用红黑树来实现的,关于创建pair类型有下面几种方法:

 
  1. pair<string,int>("苹果",5);

  2. make_pair("西瓜",1);

  3. pair<string,int> p = {"菠萝",3};

make_pair : template <class T1, class T2> pair<T1,T2> make_pair (T1 x, T2 y);

下面来简单看一下make_pair的用法:

 
  1. template <class T1,class T2>

  2. pair<T1,T2> make_pair (T1 x, T2 y)

  3. {

  4. return ( pair<T1,T2>(x,y) );

  5. }

在刚开始介绍set的时候,简单介绍了一下pair。那么现在便将pair和make_pair再做一个详细的补充吧

1、pair:

pair是将两个数据合成一个数据,当有这样的需求时就要用到pair,就是map。还有一个运用就是函数要返回连个数据的时候要用到pair,pair是一个结构体,因为两个成员变量用的是struct而不是class。

2、make_pair:

我们可以使用pair的构造函数,也可以使用make_pair来生成我们需要的pair。一般来说,在需要pair的时候我们用ake_pair来生成pair的对象很方便,但由于pair可以进行隐示的类型转换局带来一些问题,如下:

 
  1. std::pair<int, float>(1, 1.1);

  2.  
  3. std::make_pair(1, 1.1);


第一个是float,第二个就自动匹配成了double。

好了,介绍到这里就要言归正传回来说map

1、插入:insert()

1)pair<iterator,bool> insert ( const value_type& x );

插入一个value_type类型,返回的则是一个pair类型。pair<iterator,bool>就是pair<map<K,V>::iterator,bool>。如果插入成功的话bool值就返回的是true,iterator指向插入的位置,否则的话iterator就指向已经存在的这个元素的位置,iterator是一个pair<K,V>类型的迭代器。
2)iterator insert ( iterator position, const value_type& x );

在一个迭代器的位置插入一个value_type类型,插入成功的话就返回新插入位置的迭代器,否则就返回传入的迭代器。

3)template <class InputIterator>
void insert ( InputIterator first, InputIterator last );

插入的是一段迭代器区间

2、删除:erase()

1)void erase ( iterator position );

删除的是position位置的元素

2)size_type erase ( const key_type& x );

删除的是键值所在的位置,成功为1,否则为0

3)void erase ( iterator first, iterator last );

删除一段迭代器区间

3、查找:find()

  iterator find ( const key_type& x );
const_iterator find ( const key_type& x ) const;

查找成功的话会返回这个元素的迭代器,否则返回的是end

4、count:

size_type count ( const key_type& x ) const;

和set中的count使用功能相同

5、operator[]:

T& operator[] ( const key_type& x );

operator[]是很常用的,如果map中有这个x,则它就把这个x所对应的value的引用返回。如果map中没有这个x的话,则它会调用insert(pair<K,V>(k,V())),将k和V的缺省值对应起来插入后并返回这个value的引用。

  下面是一个通过map统计水果出现次数的问题:

第一种:

 
  1. void CountFruit(vector<string> t)

  2. {

  3. map<string ,int> countMap;

  4. for(size_t i = 0; i < t.size(); ++i)

  5. {

  6. map<string,int>::iterator ret = countMap.find(t[i]);

  7. if(ret != countMap.end())

  8. {

  9. ret->second++;

  10. //(*ret).second++;

  11. }

  12. else

  13. {

  14. countMap.insert(pair<string,int>(t[i],1));

  15. }

  16. }

  17. }

这种方法会遍历两次,find遍历一次,insert也要遍历一次。而且必须先进行查找,如果已存在second++,不存在直接插入就好

第二种:

 
  1. void CountFruit(vector<string> t)

  2. {

  3. map<string,int> countMap;

  4. for(size_t i = 0; i< t.size(); ++i)

  5. {

  6. pair<map<string,int>::iterator,bool> ret = countMap.insert(pair<string,int>(t[i],1));

  7. if(ret.second == false)

  8. {

  9. ret.first->second++;

  10. }

  11. }

  12. }


这种方法用insert的返回值,如果不存在,直接插入,返回指向插入位置的迭代器以及true;如果存在,返回指向已经存在位置的迭代器 和flase,然后将其second加1

第三种:

 
  1. void CountFruit(vector<string> t)

  2. {

  3. map<string,int> countMap;

  4. for(size_t i = 0; i < t.size(); ++i)

  5. {

  6. countMap[t[i]]++;

  7. }

  8. }

这种用的是operator[]没有的话就插入,有就返回value的引用。

operator[]实现的是:1、读取key的值,2、修改second的值。给定关键字key返回key对应pair的second的引用

 

版权声明:文章转载需注明出处,谢谢合作。 https://blog.csdn.net/Payshent/article/details/55223099

个人分类: C++

猜你喜欢

转载自blog.csdn.net/shufuyouqian/article/details/81187795