map和set

来源:互联网 发布:趋势密码软件好吗 编辑:程序博客网 时间:2024/06/14 02:20

关于容器我们知道的在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;

template <class T1, class T2> struct pair{  typedef T1 first_type;  typedef T2 second_type;  T1 first;  T2 second;  pair() : first(T1()), second(T2()) {}  pair(const T1& x, const T2& y) : first(x), second(y) {}  template <class U, class V>    pair (const pair<U,V> &p) : first(p.first), second(p.second) { }}
 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的用法我将通过下面的代码展示来给大家做一个进一步的说明

#include<iostream>using namespace std;#include<set>void fun(set<int> myset)  {      set<int>::iterator it;      for (it=myset.begin(); it!=myset.end(); it++)      {          cout <<*it<<" ";      }      cout << endl;    }  void TestSet()  {      set<int> t;      set<int>::iterator it;      pair<set<int>::iterator,bool> ret;      t.insert(1);      t.insert(2);      t.insert(3);      t.insert(4);      t.insert(5);      fun(t);      cout<<endl;        ret = t.insert(2);if(ret.second == false)    {          it=ret.first;        }      cout<<*it<<endl;      //第二种插入      t.insert (it,7);                       t.insert (it,8);                       t.insert (it,9);                       fun(t);      cout<<endl;      //第三种插入      int a[]= {1,11,111};                   t.insert (a,a+3);      fun(t);      cout<<endl;              cout<<"1 count:"<<t.count(10)<<endl;      cout<<"size:"<<t.size()<<endl;        t.erase (1);    fun(t);      cout<<endl;        it=t.begin();      it++;                                                  t.erase (it);       fun(t);      cout<<endl;      it=t.find (11);      t.erase ( it, t.end() );    fun(t);      cout<<endl;  }int main(){TestSet();return 0;}
程序的输出结果是:


二、map(映射)

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

pair<string,int>("苹果",5);make_pair("西瓜",1);pair<string,int> p = {"菠萝",3};
make_pair : template <class T1, class T2> pair<T1,T2> make_pair (T1 x, T2 y);

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

template <class T1,class T2>  pair<T1,T2> make_pair (T1 x, T2 y)  {    return ( pair<T1,T2>(x,y) );  }
在刚开始介绍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可以进行隐示的类型转换局带来一些问题,如下:

std::pair<int, float>(1, 1.1);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统计水果出现次数的问题:

第一种:

void CountFruit(vector<string> t){    map<string ,int> countMap;    for(size_t i = 0; i < t.size(); ++i)    {        map<string,int>::iterator ret = countMap.find(t[i]);        if(ret != countMap.end()){            ret->second++;    //(*ret).second++;        }        else        {            countMap.insert(pair<string,int>(t[i],1));        }    }}
这种方法会遍历两次,find遍历一次,insert也要遍历一次。而且必须先进行查找,如果已存在second++,不存在直接插入就好

第二种:

void CountFruit(vector<string> t){    map<string,int> countMap;    for(size_t i = 0; i< t.size(); ++i)    {        pair<map<string,int>::iterator,bool> ret = countMap.insert(pair<string,int>(t[i],1));        if(ret.second == false)        {            ret.first->second++;        }    }}

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

第三种:

void CountFruit(vector<string> t){    map<string,int> countMap;    for(size_t i = 0; i < t.size(); ++i)    {        countMap[t[i]]++;    }}
这种用的是operator[]没有的话就插入,有就返回value的引用。

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















0 0
原创粉丝点击