STL学习之map容器

map

         Map是一系列有一个键值(key)和映射值(value)组合的存储元素关联容器。

        在一个map中,key值是唯一的确定一个元素,而映射值(value)是这个key相关的值的某个排序。键的类型和值的类型是不同的,例如,map的一个典型的实例----电话簿索引是以姓名作为key,以电话号码作为value的。

        本质上,map中的元素是从低到高的键值排序伴随着一个设置在构造函数中严格的弱排序的标准。

        作为关联容器,他们特别设计了通过键值快速访问(不像通过相关联或者相对位置快速访问的顺序容器)。

         因此,下面是map作为关联容器的几个主要特征:

  • 唯一的键值:在map容器中,每个键值都是唯一的。
  • 每一个元素都是有键和值组成。元素值即为其键的简单的关联容器,需要看一下set关联容器。
  • 元素始终保持着严格的弱排序。

        map中的键唯致使此关联容器可以直接执行访问操作(operator[]),此访问操作允许访问值。

        在c++标准模板库的说明文档中,map容器有四个模板参数:

[cpp]  view plain copy
  1. template<class Key, class T., class Compare = less<Key>, class Allocator = allocator<pair<const Key,T> > > class map;  

         参数解析:

  • Key:键值的类型,map容器的每一个元素都是唯一的有键值确定。
  • T:映射值的类型,map中的每一个元素都是用于存储某些数据作为其映射值。
  • Compare:比较类:一个带有两个键类型的参数和返回一个布尔值(bool)。表达式comp(a, b),comp是比较类的对象,a和b是键值,如果a在b之前(类似a<b),返回true;也可以是执行函数操作的类或者一个指向函数的指针。它默认为less<Key>,其中less<Key>和a<b返回的值类似。map对象用这个表达式决定元素在容器中的位置。所有在map容器着哦功能的元素都始终遵守这个规则。
  • Allocator:用于定义存储分配模型的分配器对象类型,默认的情况下,使用allocator类模板,这个类模板是最简单的内存分配模型并且是值独立的。

         这个容器类支持双向迭代。

         迭代器访问map容器元素的key和value。为此,类定义了value_type类型,此类型是一个第一个值为对应的常key类型(模板参数Key)和第二个值对应的value(模板参数为T)的pair类:

          typedef pair<const Key, T> value_type;

         map容器的迭代器指向value_type类型的元素,因此,对于一次迭代调用,可以指向map元素,此元素的key和value都可以分别访问到:         

[cpp]  view plain copy
  1. map<Key, T>::iterator it;  
  2. (*it).first;           //键值  
  3. (*it).second;     //映射值  
  4. (*it)                    //元素值(pair<const Key,T>类型)  
         当然,任何其他的直接访问操作,例如->或者[]可以使用,例如:

[cpp]  view plain copy
  1. it->first;  
  2. it->second;  

成员函数


迭代器 :

容器(Capacity :

元素访问 :

修改容器操作 :

观察者(Observers :

操作 :

分配器 :

成员类型

of  template <class Key, class T, class Compare=less<Key>, class Allocator=allocator<pair <const Key, T> > > class map;

member typedefinition
key_typeKey
mapped_typeT
value_typepair<const Key,T>
key_compareCompare
value_compareNested class to compare elements (see member function value_comp)
allocator_typeAllocator
referenceAllocator::reference
const_referenceAllocator::const_reference
iteratorBidirectional iterator
const_iteratorConstant bidirectional iterator
size_typeUnsigned integral type (usually same as size_t)
difference_typeSigned integral type (usually same as ptrdiff_t)
pointerAllocator::pointer
const_pointerAllocator::const_pointer
reverse_iteratorreverse_iterator<iterator>
const_reverse_iteratorreverse_iterator<const_iterator>

map::map

explicit map ( const Compare& comp = Compare(),
               const Allocator& = Allocator() );
template <class InputIterator>
  map ( InputIterator first, InputIterator last,
        const Compare& comp = Compare(), const Allocator& = Allocator() );
map ( const map<Key,T,Compare,Allocator>& x );
(Key, T, Compare and Allocator
map构造函数

构造一个map容器对象,依据下面的构造函数初始化容器内容:

explicit map ( const Compare& comp = Compare(), Allocator& = Allocator() );
默认构造函数:构造一个空的map对象,这个对象没有内容并且大小为0。

template <class InputIterator>
map ( InputIterator first, InputIterator last, const Compare& comp= Compare(), const Allocator& = Allocator() );
    迭代构造函数:在第一个和最后一个之间迭代,设定每个元素序列的拷贝作为容器对象的内容。

map ( const map<Key,T,Compare,Allocator>& x );
     拷贝构造函数:对象初始化为和x对象有着相同的内容和属性。

参数
first, last

     容器序列中的第一个位置和最后一个位置的输入迭代器,范围为[first,last),包括所有的在first和last之间的元素,其中last是容器中最后一个元素的下一个位置。函数模板类型是任意的输入迭代器 的类型。
x
     有着相同的类模板参数(Key,T,Compare and Allocator)的另一个map对象。
comp

    用于严格的弱排序(weak ordering)的比较对象。
   Compare是第三个类模板参数。
unnamed Allocator parameter

    用于替代构造一个新的Allocator对象。
    对于类实例采用默认分配器类模板的版本,这个参数是不相关的。

实例
[cpp]  view plain copy
  1. // constructing maps  
  2. #include <iostream>  
  3. #include <map>  
  4. using namespace std;  
  5.   
  6. bool fncomp (char lhs, char rhs) {return lhs<rhs;}  
  7.   
  8. struct classcomp {  
  9.   bool operator() (const char& lhs, const char& rhs) const  
  10.   {return lhs<rhs;}  
  11. };  
  12.   
  13. int main ()  
  14. {  
  15.   map<char,int> first;  
  16.   
  17.   first['a']=10;  
  18.   first['b']=30;  
  19.   first['c']=50;  
  20.   first['d']=70;  
  21.   
  22.   map<char,int> second (first.begin(),first.end());  
  23.   
  24.   map<char,int> third (second);  
  25.   
  26.   map<char,int,classcomp> fourth;                 // class as Compare  
  27.   
  28.   bool(*fn_pt)(char,char) = fncomp;  
  29.   map<char,int,bool(*)(char,char)> fifth (fn_pt); // function pointer as Compare  
  30.   
  31.   return 0;  
  32. }  

map::count

size_type count ( const key_type& x ) const;

计算map中指定key出现的次数,由于map容器中key值是不允许重复的,所以函数实际返回的是:1,指定的key在容器中;0,指定的key不在容器中。

参数

x
           需要搜索的key值。key_type是一个map容器的成员类型,是key的一个别名。

返回值

如果容器中有指定key的元素,返回1,或者返回0。

size_type成员类型是一个无符号的整数类型。

举例

[cpp]  view plain copy
  1. #include <iostream>  
  2. #include <map>  
  3.   
  4. using namespace std;  
  5.   
  6. int main()  
  7. {  
  8.     map<charint> mymap;  
  9.     char c;  
  10.       
  11.     mymap['a'] = 101;  
  12.     mymap['c'] = 202;  
  13.     mymap['f'] = 303;  
  14.   
  15.     for (c='a'; c<'h'; c++)  
  16.     {  
  17.         cout << c;  
  18.         if (mymap.count(c)>0)  
  19.         {  
  20.             cout << " is an element of mymap." << endl;  
  21.         }  
  22.         else  
  23.         {  
  24.             cout << " is not an element of mymap." << endl;  
  25.         }  
  26.     }  
  27.     return 0;  
  28. }  
执行结果
[cpp]  view plain copy
  1. liujl@liujl-Rev-1-0:~/mycode/STL$ ./map_count   
  2. a is an element of mymap.  
  3. b is not an element of mymap.  
  4. c is an element of mymap.  
  5. d is not an element of mymap.  
  6. e is not an element of mymap.  
  7. f is an element of mymap.  
  8. g is not an element of mymap.  

map::insert

[cpp]  view plain copy
  1. pair<iterator,bool> insert(const value_type& x);  
  2.                      iterator insert(iterator position, const value_type& x);  
  3. template<class InputIterator>  
  4.                           void insert(InputIterator first, InputIterator last);  
插入元素

map容器可以插入单个新元素(如果使用参数x)或者元素序列(如果使用输入迭代器)。

随着插入元素数量增加,容器的size也随着增加。

由于map容器不允许键值重复,所以插入操作需要确保要插入的key值在map容器中没有。如果有的话,新的元素是不允许插入的,并且此键值的映射值是不会发生改变的。

如果想允许插入相同的元素,可以参考multimap。

本质上,map容器保持所有元素按照结构体指定的比较对象排序。

map容器允许直接的访问通过map::operator[]操作(对[]操作符进行了重载),即可以通过object[key]=value;这样操作。

参数

x

    初始化插入元素的值。

position

 确定插入操作时第一个相比较的元素。该参数并不是强制插入元素的位置。

first,last

指定元素区间的迭代器。拷贝[first,last)区间的元素,并且插入到map容器中。


返回值

第一个版本的insert返回一个pair类型,pair类型的成员pair:first设置一个迭代器指针,这个迭代器指针可能指向新插入的元素或者已经在map容器中存在的有着相同key值的元素;成员pair:second元素,如果新的元素插入,返回为true,或者当已经存在相同的key,返回false。

第二个版本返回一个指向新插入的元素或者已经在map容器中存在的有着相同key值的元素的迭代器指针。

迭代器是一个成员类型,被定义成双向迭代器类型。

举例1:

[cpp]  view plain copy
  1. #include <string>  
  2. #include <iostream>  
  3. #include <map>  
  4. #include <utility>  
  5.   
  6. using namespace std;  
  7.   
  8. int main(void)  
  9. {  
  10.         map<string, int> Employees;  
  11.   
  12.         Employees["Mike C."] = 12306;  
  13.         Employees["Charlie M."] = 95555;  
  14.         //使用pair  
  15.         Employees.insert(std::pair<string, int>("David D.", 1984));  
  16.         Employees.insert(map<string, int>::value_type("John A.", 7582));  
  17.         Employees.insert(make_pair("Peter Q.", 5328));  
  18.   
  19.         cout << "Map size: " << Employees.size() <<  endl;  
  20.   
  21.         for (map<string, int>::iterator ii= Employees.begin(); ii != Employees.end(); ++ii)  
  22.         {  
  23.                     cout << (*ii).first << ":" << (*ii).second << endl;  
  24.         }  
  25.         return 0;  
  26. }                                                  
执行结果:

[cpp]  view plain copy
  1. liujl@liujl-Rev-1-0:~/mycode/STL$ ./mapEx2  
  2. Map size: 5  
  3. Charlie M.:95555  
  4. David D.:1984  
  5. John A.:7582  
  6. Mike C.:12306  
  7. Peter Q.:5328  
实例2:

[cpp]  view plain copy
  1. #include <iostream>  
  2. #include <map>  
  3.   
  4. using namespace std;  
  5.   
  6. int main(void)  
  7. {  
  8.     map<charint> mymap;  
  9.     map<charint>::iterator it;  
  10.     pair<map<charint>::iterator, bool> ret;  
  11.   
  12.     //first insert function version  
  13.     mymap.insert( pair<charint>('a', 100) );  
  14.     mymap.insert( make_pair('d', 200) );  
  15.     mymap.insert( map<charint>::value_type('z', 500));  
  16.       
  17.     //check return value  
  18.     ret = mymap.insert( pair<charint>('z', 800));  
  19.     if (ret.second == false)  
  20.     {  
  21.         cout << " element 'z' already existed!";  
  22.         cout << " with a value of " << ret.first->second << endl;  
  23.     }  
  24.   
  25.     //second insert function version  
  26.     it = mymap.begin();  
  27.     mymap.insert(it, pair<charint>('b', 300));  
  28.     mymap.insert(it, pair<charint>('c', 400));  
  29.       
  30.     //third insert function version  
  31.     map<charint> othermap;  
  32.     othermap.insert(mymap.begin(), mymap.end());  
  33.     //othermap.insert(mymap.begin(), mymap.find('c'));  
  34.       
  35.     //print container contents:  
  36.   
  37.     cout << "mymap contains: " << endl;  
  38.     for (it = mymap.begin(); it != mymap.end(); it++)  
  39.         cout << (*it).first << "=>" << (*it).second << endl;  
  40.       
  41.     cout << "other contains: " << endl;  
  42.     for (it=othermap.begin(); it != othermap.end(); it++)  
  43.         cout << (*it).first << "=>" << (*it).second << endl;  
  44.     return 0;  
  45. }  

map::find

[cpp]  view plain copy
  1. iterator find ( const key_type& x );  
  2. const iterator find( const key_type& x) const;  

获取元素的迭代器

获取map容器中指定键值x的元素,如果找到,返回此元素的迭代器,否则返回map::end()的迭代器(即查找到容器的末尾都没有找到此元素)。

前面章节介绍的map::count成员函数也可以有类似的功能,详见STL学习之map容器(1)介绍。

参数

x  

       需要查找的键值。

        Key_type是map容器定义的作为Key别名的一个成员类型。

返回值

    指向元素的迭代器,如果指定的键值找到,返回找到元素的迭代器或者指定的键值没有找到返回map::end。

   

实例:

[cpp]  view plain copy
  1. #include <iostream>  
  2. #include <map>  
  3.   
  4. using namespace std;  
  5.   
  6. int main(void)  
  7. {  
  8.     map<charint> mymap;  
  9.     map<charint>::iterator it;  
  10.       
  11.     mymap['a'] = 50;  
  12.     mymap['b'] = 100;  
  13.     mymap['c'] = 150;  
  14.     mymap['d'] = 200;  
  15.   
  16.     it = mymap.find('b');  
  17.     mymap.erase(it);  
  18.     mymap.erase(mymap.find('d'));  
  19.   
  20.     cout << "mymap contains:" << endl;  
  21.     for (it = mymap.begin(); it != mymap.end(); ++it)  
  22.         cout << (*it).first << "=>" << (*it).second << endl;  
  23.       
  24.     cout << " elements in mymap:" << endl;  
  25.     cout << " a=> " << mymap.find('a')->second << endl;  
  26.     cout << " b=> " << mymap.find('b')->second << endl;  
  27.     cout << " c=> " << mymap.find('c')->second << endl;  
  28.     cout << " d=> " << mymap.find('d')->second << endl;  
  29.     return 0;  
  30. }  

执行结果:

[cpp]  view plain copy
  1. liujl@liujl-Rev-1-0:~/mycode/STL$ g++ map_find.cpp -o map_find  
  2. liujl@liujl-Rev-1-0:~/mycode/STL$ ./map_find  
  3. mymap contains:  
  4. a=>50  
  5. c=>150  
  6.  elements in mymap:  
  7.  a=> 50  
  8.  b=> -1076412860 //不存在  
  9.  c=> 150  
  10.  d=> -1076412860 //不存在  

map::erase

[cpp]  view plain copy
  1. void erase( iterator postion );  
  2. size_type erase( const key_type& x );  
  3. void erase( iterator first, iterator last );  

删除元素

从map容器中删除一个元素或者一个区间的元素([first, last));

参数

postion

        指向被map容器中删除元素迭代器指针。

        iterator是一个成员类型,定义作为双向迭代器类型。

x

       从map容器中移除的元素值。

first,last

        指定迭代器区间[first,last),需要从map容器中删除的区间。

返回值

       仅第二个版本,函数返回需要删除的元素个数。

实例:

      

[cpp]  view plain copy
  1. // erasing from map  
  2. #include <iostream>  
  3. #include <map>  
  4. using namespace std;  
  5.   
  6. int main ()  
  7. {  
  8.   map<char,int> mymap;  
  9.   map<char,int>::iterator it;  
  10.   
  11.   // insert some values:  
  12.   mymap['a']=10;  
  13.   mymap['b']=20;  
  14.   mymap['c']=30;  
  15.   mymap['d']=40;  
  16.   mymap['e']=50;  
  17.   mymap['f']=60;  
  18.   
  19.   it=mymap.find('b');  
  20.   mymap.erase (it);                   // erasing by iterator  
  21.   
  22.   mymap.erase ('c');                  // erasing by key  
  23.   
  24.   it=mymap.find ('e');  
  25.   mymap.erase ( it, mymap.end() );    // erasing by range  
  26.   
  27.   // show content:  
  28.   for ( it=mymap.begin() ; it != mymap.end(); it++ )  
  29.     cout << (*it).first << " => " << (*it).second << endl;  
  30.   
  31.   return 0;  
  32. }  

执行结果:

[cpp]  view plain copy
  1. liujl@liujl-Rev-1-0:~/mycode/STL$ g++ map_erase.cpp -o map_erase  
  2. liujl@liujl-Rev-1-0:~/mycode/STL$ ./map_erase   
  3. a => 10  
  4. d => 40  

map::lower_bound 

[cpp]  view plain copy
  1. iterator lower_bound( const key_type& x );  
  2. const iterator lower_bound( const key_type& x ) const;  

返回指向下界的迭代器

返回一个指向容器中第一个键值大于或者等于x元素迭代器。

map::upper_bound

[cpp]  view plain copy
  1. iterator upper_bound( const key_type& x );  
  2. const iterator upper_bound( const key_type& x ) const;  
返回指向上界的迭代器

返回一个指向容器中第一个键值大于x元素迭代器。

从定义中可以看到upper_bound和lower_bound区别。

upper_bound和lower_bound参数

x

      比较的键值。

     

实例:

[cpp]  view plain copy
  1. #include <iostream>  
  2. #include <map>  
  3.   
  4. using namespace std;  
  5.   
  6. int main(void)  
  7. {  
  8.     map<charint> mymap;  
  9.     map<charint>::iterator it, itlow, itup;  
  10.       
  11.     mymap['a'] = 20;  
  12.     mymap['b'] = 40;  
  13.     mymap['c'] = 60;  
  14.     mymap['d'] = 80;  
  15.     mymap['e'] = 100;  
  16.   
  17.     itlow = mymap.lower_bound('b');  
  18.     itup = mymap.upper_bound('d');  
  19.   
  20.     mymap.erase(itlow, itup);  
  21.       
  22.     for( it= mymap.begin(); it != mymap.end(); ++it)  
  23.         cout << (*it).first << "=>" << (*it).second << endl;  
  24.     return 0;  
  25. }  

执行结果:

[cpp]  view plain copy
  1. liujl@liujl-Rev-1-0:~/mycode/STL$ g++ map_bound.cpp -o map_bound  
  2. liujl@liujl-Rev-1-0:~/mycode/STL$ ./map_bound   
  3. a=>20  
  4. e=>100  

执行结果:

[cpp]  view plain copy
  1. liujl@liujl-Rev-1-0:~/mycode/STL$ vim map_insert.cpp  
  2. liujl@liujl-Rev-1-0:~/mycode/STL$ g++ map_insert.cpp  -o map_insert  
  3. liujl@liujl-Rev-1-0:~/mycode/STL$ ./map_insert  
  4.  element 'z' already existed! with a value of 500  
  5. mymap contains:   
  6. a=>100  
  7. b=>300  
  8. c=>400  
  9. d=>200  
  10. z=>500  
  11. other contains:   
  12. a=>100  
  13. b=>300  
  14. c=>400  
  15. d=>200  
  16. z=>500  

std::map的insert和下标[]访问

在map中插入元素

改变map中的条目非常简单,因为map类已经对[]操作符进行了重载

enumMap[1] = "One";
enumMap[2] = "Two";
.....

这样非常直观,但存在一个性能的问题。插入2时,先在enumMap中查找主键为2的项,没发现,然后将一个新的对象插入enumMap,键是2,值是一个空字符串,插入完成后,将字符串赋为"Two"; 该方法会将每个值都赋为缺省值,然后再赋为显示的值,如果元素是类对象,则开销比较大。我们可以用以下方法来避免开销:

enumMap.insert(map<int, CString> :: value_type(2, "Two"))

 

 

insert()方法:若插入的元素的键值已经存在于map中,那么插入就会失败,不会修改元素的键对应的值;若键值在map中查不到,那么就会将该新元素加到map中去。

下标[key]方法:若插入元素的键值已经存在于map中,那么会更新该键值对应的值为新的元素的值;若该键值在map中找不到,那么就会新建一个键值为该键(key)的元素,并将key对应的值赋值为默认值(默认构造函数生成的对象)



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值