C++进阶:STL容器-map

1. 简介

mapkey-value构成的集合。

2. 操作

map是键值对<key,value>构据集合。key必须唯一。

  • 主要用来查找key对应value,要求key必须是可排序的,必须支持<比较运算符。
  • map默认是以key升序存放键值对<key,value>数据,比较适合二分查找。

map内部结构

map使用pair<key,value>类模板保存key与value,pair<key,value>有两个public成员变量:firstsecond,first存放key,second存放value。在map里面可以使用map<>::value_type表示pair<key,value>

typedef pair<key,value> value_type;

2.1 初始化

  1. 默认构造(可带参数)
  2. 复制构造
  3. 范围赋值构造

初始化时必须给map<>类模板同时设置key与value的类型模板实参。
实参类型不限于基本类型、类类型(class、struct、union),还可以是容器模板。

2.2 基本操作

  • 迭代器
迭代器 作用
c.begin() 头迭代器
c.end() 尾迭代器
c.rbegin() 反向头迭代器
c.rend() 反向尾迭代器

vector相似。

  • 数据量操作
函数 作用
c.size() 大小
c.max_size() 最大大小
c.empty() 判空
c.clear() 清空

2.3 添加数据

  1. insert插入pair<>数据
#include <iostream>
#include <map>
#include <algorithm>
using namespace std;
void Display(map<int,int>::value_type const& val){
    cout << val.first <<" " << val.second << endl;
}
int main(){
    map<int,int> m;
    for(int i=0;i<10;i++){
        m.insert(pair<int,int>(i,i*10));
    }
    for_each(m.begin(),m.end(),Display);
}
  1. insert插入map<>::value_type数据
#include <iostream>
#include <map>
#include <algorithm>
using namespace std;
void Display(map<int,int>::value_type const& val){
    cout << val.first <<" " << val.second << endl;
}
int main(){
    map<int,int> m;
    for(int i=0;i<10;i++){
        m.insert(map<int,int>::value_type(i,i*10));
    }
    for_each(m.begin(),m.end(),Display);
}
  1. insert插入make_pair数据

make_pair是一个函数模板,类似与如下实现:

template<class K,class V)
inline pair<K,V> make_pair(K const& k,V const& v){
    return pair<K,V>(k,v);
}
#include <iostream>
#include <map>
#include <algorithm>
using namespace std;
void Display(map<int,int>::value_type const& val){
    cout << val.first <<" " << val.second << endl;
}
int main(){
    map<int,int> m;
    for(int i=0;i<10;i++){
        m.insert(make_pair(i,i*10));
    }

    for_each(m.begin(),m.end(),Display);
}
  1. 下标运算符[]添加数据
#include <iostream>
#include <map>
#include <algorithm>
using namespace std;
void Display(map<int,int>::value_type const& val){
    cout << val.first <<" " << val.second << endl;
}
int main(){
    map<int,int> m;
    for(int i=0;i<10;i++){
        m[i] = i*10;
    }
    for_each(m.begin(),m.end(),Display);
}

说明:

  • map只有在访问key,如果key不存在则会创建,反之,使用已存在的<key,val>。对于已存在的keyinsert()操作是无法插入数据,可以通过判断insert()的返回值pair<map<>::iterator,bool>,得知是否插入成功。

vector为空,是否可以使用下标运算符添加数据?例如:vec[2]=3;

2.4 遍历

  • 迭代器for循环
for(map<int,int>::iterator it = m.begin();it != m.end();it++){
        cout << "[" << it->first << "]=" << it->second() << endl; 
}
  • for_each()循环
    定义函数指针
inline void Display(map<int,int>::value_type const& val){
    cout << "[" << val.first << "]=" << val.second << endl;
}

执行for_each

for_each(m.begin(),m.end(),Display);
  • C++11auto迭代器写法
for(auto it = m.begin();it != m.end();it++){
        cout << "[" << it->first << "]=" << it->second() << endl; 
}
  • C++11 for-loop-scope迭代器写法
for(auto p : m){
    cout << "[" << p.first << "]=" << p.second << endl;
}
  • C++11 for_each()与lamdba表达式
for_each(m.begin(),m.end(),[](map<int,int>::value_type& p){
    cout << "[" << p.first << "]=" << p.second << endl;
});

2.5 key查找

  1. count()判断key是否存在
if(m.count(key) == 1){
     ...
}
  1. find()判断key是否存在以及位置
map<int,int>::iterator it = m.find(key);
if(m.end() != it){
     ...
}
  1. 下标运算符[]
m[key];

如果key不存在,默认创建。

2.6 区域查找

成员变量 作用
m.lower_bound(key) key下边界
m.upper_bound(key) key上边界
m.equal_range(key) key上下边界

2.7 删除

  1. 关键字删除
m.erase(key);
  1. 迭代器删除
m.erase(m.begin());
  1. 区域删除
m.erase(it_a,it_b);

2.8 排序

默认按照key升序排列。自定义排序是,可以在实例化加上keycomp仿函数,重载<运算符。

map<key类型,value类型,comp> m;

3. 实例

1.两个数组合并成一个map

#include <iostream>
#include <map>
#include <iterator>
#include <algorithm>
using namespace std;
void Display(map<int,int>::value_type const& val){
    cout << "[" << val.first << "]=" << val.second << endl;
}
class MapMaker{
public:
    MapMaker(map<int,int>& m):m_(m){}
    inline bool operator()(int k,int v){
        return m_.insert(make_pair(k,v)).second;
    }
private:
    map<int,int>& m_;
};
int main(){
    map<int,int> m;
    int arr1[] = {1,2,1,4,5,2,3,4}; 
    int arr2[] = {19,29,39,49,59,69,79,89}; 
    bool res[8];
    transform(arr1,arr1+8,arr2,res,MapMaker(m));
    cout<< boolalpha;
    copy(res,res+8,ostream_iterator<bool>(cout,","));
    cout<< noboolalpha << endl;
    for_each(m.begin(),m.end(),Display);
}

在C++11中transform可以使用lamdba表达式,改写成

transform(arr1,arr1+8,arr2,res,[&m](int k,int v){
    return m.insert(make_pair(k,v)).second;
});

2.把map的key和value各自分解成一个vector

#include <iostream>
#include <algorithm>
#include <iterator> // ostream_iterator
#include <vector>
#include <map>
using namespace std;
// 仿函数
class Spliter{
public:
    Spliter(vector<int>& k,vector<int>& v):k_(k),v_(v){}
    void operator()(map<int,int>::value_type const& pair){
        k_.push_back(pair.first);
        v_.push_back(pair.second);
    }
private:
    vector<int>& k_;
    vector<int>& v_;
};
int main () {
  map<int,int> m;
  for(int i=0;i<10;i++){
    m[i] = i*10;
  }
  vector<int> keys;
  vector<int> values;
  for_each(m.begin(),m.end(),Spliter(keys,values));
  copy(keys.begin(),keys.end(),ostream_iterator<int>(cout,","));
  cout << endl;
  copy(values.begin(),values.end(),ostream_iterator<int>(cout,","));
  return 0;
}

在C++11中for_each可以使用lamdba表达式,改写成

for_each(m.begin(),m.end(),[&keys,&values](map<int,int>::value_type const& pair){
        keys.push_back(pair.first);
        values.push_back(pair.second);
});

使用C++11 for-loop-scope语法

for(auto p:m){
    keys.push_back(p.first);
    values.push_back(p.second);
}
  1. map的key和value互换

4. 练习

面试题 16.02. 单词频率

205. 同构字符串

383. 赎金信

49. 字母异位词分组

容器综合练习

1418. 点菜展示表

1. 两数之和

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容