博客
关于我
C++ map 和 multimap 容器
阅读量:515 次
发布时间:2019-03-07

本文共 7898 字,大约阅读时间需要 26 分钟。

map/multimap的简介

map是标准的关联式容器,一个map里存储的元素是一个键值对序列,叫做(key,value)键值对。它提供基于key快速检索数据的能力。

  1. map中key值是唯一的。集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入位置。
  2. map底层的具体实现是采用红黑树变体的平衡二叉树的数据结构。在插入操作、删除和检索操作上比vector快很多。
  3. map可以直接存取key所对应的value,支持[]操作符,如map[key]=value。
  4. 使用时必须包含头文件#include <map>

multimap与map的区别:

map支持唯一键值,每个键只能出现一次;而multimap中相同键可以出现多次。multimap不支持[]操作符。

map/multimap容器 和 set/multiset容器都是差不多的,只是map/mulitmap比他们多了一个键值!

如果不懂set/multiset容器的可以点下面链接:

当然,map/multimap容器也有仿函数,因为在之前的文章中,已经详细讲过了,所以这里就不在讲了,如果不懂的可以点下面链接去学习:


定义
// 无参	map
m1; map
m2; map
m3; map
m4; // 带参 map
m5(m1.begin(), m1.end()); // 迭代器 map
m6(m3); // 调用拷贝构造函数 map
m7 = m4; // 调用了赋值构造函数

还可以用各种指针类型或自定义类型


插入

// 方式一 构造一个pair,然后插入,如果键存在,则插入失败

m1.insert(pair<int, string>(1, “张三”));

// 方式二 使用make_pair

m1.insert(make_pair(2, “李四”));

// 方式三 使用value_type,相当于pair<int, string>

m1.insert(map<int, string>::value_type(3, “王五”));

// 方式四 使用 [] 重载,如果键值对已经存在,则覆盖原值

m1[4] = “赵六”;
m1[4] = “韩七”;

注意:

  1. 方式一 至 方式三的返回值类型都是一样的,都是

    pair<iterator,bool> 类型

  2. 第四种方法非常直观,但碰到相同的键时会进行覆盖操作。比如插入key 为4的键值时,先在mapStu中查找主键为4的项,若不存在,则将一个键为4,值为默认初始化值的对组插入到mapStu中,然后再将值修改成“赵六”。若发现已存在4这个键,则修改这个键对应的value。

  3. string strName = mapStu[8]; //取值操作或插入操作

  4. 只有当mapStu存在8这个键时才是正确的取操作,否则会自动插入一个实例,键为8,值为默认构造时的初始化值。

下面测试代码 函数 test1 中会有详细案例


迭代器

// 返回容器中第一个数据的迭代器

m1.begin();

// 返回容器中最后一个数据之后的迭代器

m1.end();

// 返回容器中倒数第一个元素的迭代器

m1.rbegin();

// 返回容器中倒数最后一个元素的后面的迭代器

m1.rend();

// 使用迭代器方式输出容器里的值

for (map
::iterator it = m1.begin(); it != m1.end(); it++) { cout << "key:" << (*it).first << " value:" << (*it).second << endl;}

排序

map 和 multimap 容器默认存储时是顺序存储的,即

map<int, string> m1; 相等于: map<int, string, less<int>> m1;

也可以使用greater定义一个容器,使其默认逆序存储,即

map<int, string, greater<int>> m2;

在此条链接中会有详细解析:

// 交换容器中的元素

m3.swap(m2);


// 返回容器中元素的个数

m1.size();

// 判断容器是否为空

m1.empty(); // 为空返回真,不为空返回假

//删除迭代器所指的元素,返回下一个元素的迭代器

m1.erase(m1.begin());

//删除区间[beg,end)的所有元素,返回下一个元素的迭代器

m1.erase(beg, end);

//删除容器中key为key的对组,返回删除的对组个数

m1.erase(8);

// 删除容器中所有的元素

m1.clear();


查找

map方式

// 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end();

/*---map---*/// 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end();map
::iterator it = m1.find(5);if (it != m1.end()) { cout << "m1.find(5) = " << (*it).second << endl;} else { cout << "没找到!!!" << endl;}

multimap方式

// 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end();

/*---multimap---*/// 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end();multimap
::iterator mit = m2.find(111);if (mit != m2.end()) { for (; mit != m2.end(); mit++) { if ((*mit).first == 111) { cout << "m2.find(111) = " << (*mit).second << endl; } else { break; } }}

// 返回容器中键值为key的对组个数。对map来说,要么是0,要么是1;对multimap来说,值>=0

m1.count(222);

// 返回第一个 >= key 元素的迭代器

m1.lower_bound(2);

// 返回第一个 > key 元素的迭代器

m1.upper_bound(2);

//返回容器中key与keyElem相等的上下限的两个迭代器。上限是闭区间,下限是开区间,如[beg,end)

//m1.equal_range(keyElem);
m1.equal_range(7);

返回值是: pair<iterator, iterator> 类型

在下面测试代码函数 test7 中会有详细案例。


测试代码:

#include #include 
#include
#include
using namespace std;// 定义void test1(void) { // 无参 map
m1; map
m2; map
m3; map
m4; m1.insert(pair
(1, "张三")); m1.insert(pair
(2, "李四")); // 带参 map
m5(m1.begin(), m1.end()); // 迭代器 map
m6(m3); // 调用拷贝构造函数 map
m7 = m4; // 调用了赋值构造函数 for (map
::iterator it = m1.begin(); it != m1.end(); it++) { cout << "key:" << (*it).first << " value:" << (*it).second << endl; }}// insert插入void test2(void) { map
m1; // 方式一 构造一个pair,然后插入,如果键存在,则插入失败 m1.insert(pair
(1, "张三")); // 方式二 使用make_pair m1.insert(make_pair(2, "李四")); // 方式三 使用value_type,相当于pair
m1.insert(map
::value_type(3, "王五")); // 方式四 使用 [] 重载,如果键值对已经存在,则覆盖原值 m1[4] = "赵六"; m1[4] = "韩七"; m1[5] = m1[6]; // 应为两个都是新值,所以他们创建键后,值默认为空 m1[7] = m1[4]; // 将键值为4里的值赋值给键值为7的值 m1[0] = m1[8]; // 新键赋值给旧键,它两的值都为空 // 方式一 至 方式三的返回值类型都是一样的 pair
::iterator, bool> ret1 = m1.insert(pair
(9, "刘八")); pair
::iterator, bool> ret2 = m1.insert(make_pair(10, "杨九")); pair
::iterator, bool> ret3 = m1.insert(map
::value_type(11, "吴十")); if (ret1.second == true) { cout << "插入成功!value:" << (*(ret1.first)).second << endl; } else { cout << "插入失败!" << endl; } for (map
::iterator it = m1.begin(); it != m1.end(); it++) { cout << "key:" << (*it).first << " value:" << (*it).second << endl; }}// 迭代器void test3(void) { map
m1; m1.begin(); // 返回容器中第一个数据的迭代器。 m1.end(); // 返回容器中最后一个数据之后的迭代器。 m1.rbegin(); // 返回容器中倒数第一个元素的迭代器。 m1.rend(); // 返回容器中倒数最后一个元素的后面的迭代器。}// 排序void test4(void) { map
m1; // 默认是less顺序排序 //map
> m1; m1.insert(pair
(1, "张三")); m1.insert(pair
(2, "李四")); m1.insert(pair
(3, "王五")); m1.insert(pair
(4, "赵六")); // 可以使用greater逆序排序 map
> m2; m2.insert(pair
(1, "韩七")); m2.insert(pair
(2, "刘八")); m2.insert(pair
(3, "杨九")); map
> m3; // 交换容器中的元素 m3.swap(m2); cout << "m1 ==> less
:" << endl; for (map
::iterator it = m1.begin(); it != m1.end(); it++) { cout << "key:" << (*it).first << " value:" << (*it).second << endl; } cout << "m3 ==> greater
:" << endl; for (map
::iterator it = m3.begin(); it != m3.end(); it++) { cout << "key:" << (*it).first << " value:" << (*it).second << endl; }}// 大小void test5(void) { map
m1; m1.insert(pair
(1, "张三")); m1.insert(pair
(2, "李四")); m1.insert(pair
(3, "王五")); m1.insert(pair
(4, "赵六")); // 返回容器中元素的个数 m1.size(); // 判断容器是否为空 m1.empty(); // 为空返回真,不为空返回假 if (!m1.empty()) { cout << "容器元素个数为:" << m1.size() << endl; } else { cout << "容器为空!" << endl; }}// 删除void test6(void) { map
m1; m1.insert(pair
(1, "张三")); m1.insert(pair
(2, "李四")); m1.insert(pair
(3, "王五")); m1.insert(pair
(4, "赵六")); m1.insert(pair
(5, "韩七")); m1.insert(pair
(6, "刘八")); m1.insert(pair
(7, "杨九")); m1.insert(pair
(8, "吴十")); //删除迭代器所指的元素,返回下一个元素的迭代器 m1.erase(m1.begin()); // 李四,王五,赵六,韩七,刘八,杨九,吴十 map
::iterator beg = m1.begin(); beg++; map
::iterator end = m1.begin(); end++; end++; end++; //删除区间[beg,end)的所有元素,返回下一个元素的迭代器 m1.erase(beg, end); // 李四,韩七,刘八,杨九,吴十 //删除容器中key为key的对组,返回删除的对组个数 m1.erase(8); // 李四,韩七,刘八,杨九 for (map
::iterator it = m1.begin(); it != m1.end(); it++) { cout << "key:" << (*it).first << " value:" << (*it).second << endl; } // 删除容器中所有的元素 m1.clear();}// 查找void test7(void) { map
m1; multimap
m2; m1.insert(pair
(1, "张三")); m1.insert(pair
(2, "李四")); m1.insert(pair
(3, "王五")); m1.insert(pair
(4, "赵六")); m1.insert(pair
(5, "韩七")); m1.insert(pair
(6, "刘八")); m1.insert(pair
(7, "杨九")); m1.insert(pair
(8, "吴十")); m2.insert(pair
(111, "张三")); m2.insert(pair
(111, "李四")); m2.insert(pair
(222, "王五")); m2.insert(pair
(222, "赵六")); /*---map---*/ // 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end(); map
::iterator it = m1.find(5); if (it != m1.end()) { cout << "m1.find(5) = " << (*it).second << endl; } else { cout << "没找到!!!" << endl; } /*---multimap---*/ // 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end(); multimap
::iterator mit = m2.find(111); if (mit != m2.end()) { for (; mit != m2.end(); mit++) { if ((*mit).first == 111) { cout << "m2.find(111) = " << (*mit).second << endl; } else { break; } } } //返回容器中键值为key的对组个数。对map来说,要么是0,要么是1;对multimap来说,值>=0 m1.count(222); //返回第一个 >= key 元素的迭代器 it = m1.lower_bound(2); if (it != m1.end()) { cout << "找到啦!==> " << (*it).second << endl; } else { cout << "没找到!" << endl; } // 返回第一个 > key 元素的迭代器 it = m1.upper_bound(2); if (it != m1.end()) { cout << "找到啦!==> " << (*it).second << endl; } else { cout << "没找到!" << endl; } //返回容器中key与keyElem相等的上下限的两个迭代器。上限是闭区间,下限是开区间,如[beg,end) //m1.equal_range(keyElem); pair
::iterator, map
::iterator> iit = m1.equal_range(7); // 第一个迭代器 if (iit.first != m1.end()) { cout << "begin ==> " << (*iit.first).second << endl; } else { cout << "没找到!" << endl; } // 第二个迭代器 if (iit.second != m1.end()) { cout << "end ==> " << (*iit.second).second << endl; } else { cout << "没找到!" << endl; }}int main(void) { //test1(); //test2(); //test3(); //test4(); //test5(); //test6(); //test7(); system("pause"); return 0;}

总结:

STL容器中,所有容器的接口用法都是差不多的,所以说其实并不难,只要理解了一种,其他的容器用法都全会了。

转载地址:http://hrpjz.baihongyu.com/

你可能感兴趣的文章
NIFI1.21.0_NIFI和hadoop蹦了_200G集群磁盘又满了_Jps看不到进程了_Unable to write in /tmp. Aborting----大数据之Nifi工作笔记0052
查看>>
NIFI1.21.0_Postgresql和Mysql同时指定库_指定多表_全量同步到Mysql数据库以及Hbase数据库中---大数据之Nifi工作笔记0060
查看>>
NIFI1.21.0最新版本安装_连接phoenix_单机版_Https登录_什么都没改换了最新版本的NIFI可以连接了_气人_实现插入数据到Hbase_实际操作---大数据之Nifi工作笔记0050
查看>>
NIFI1.21.0最新版本安装_配置使用HTTP登录_默认是用HTTPS登录的_Https登录需要输入用户名密码_HTTP不需要---大数据之Nifi工作笔记0051
查看>>
NIFI1.21.0通过Postgresql11的CDC逻辑复制槽实现_指定表多表增量同步_增删改数据分发及删除数据实时同步_通过分页解决变更记录过大问题_02----大数据之Nifi工作笔记0054
查看>>
NIFI1.21.0通过Postgresql11的CDC逻辑复制槽实现_指定表多表增量同步_增加修改实时同步_使用JsonPath及自定义Python脚本_03---大数据之Nifi工作笔记0055
查看>>
NIFI1.21.0通过Postgresql11的CDC逻辑复制槽实现_指定表多表增量同步_插入修改删除增量数据实时同步_通过分页解决变更记录过大问题_01----大数据之Nifi工作笔记0053
查看>>
NIFI1.21.0通过Postgresql11的CDC逻辑复制槽实现_指定表或全表增量同步_实现指定整库同步_或指定数据表同步配置_04---大数据之Nifi工作笔记0056
查看>>
NIFI1.23.2_最新版_性能优化通用_技巧积累_使用NIFI表达式过滤表_随时更新---大数据之Nifi工作笔记0063
查看>>
NIFI从MySql中增量同步数据_通过Mysql的binlog功能_实时同步mysql数据_根据binlog实现update数据实时同步_实际操作05---大数据之Nifi工作笔记0044
查看>>
NIFI从MySql中增量同步数据_通过Mysql的binlog功能_实时同步mysql数据_根据binlog实现数据实时delete同步_实际操作04---大数据之Nifi工作笔记0043
查看>>
NIFI从MySql中增量同步数据_通过Mysql的binlog功能_实时同步mysql数据_配置binlog_使用处理器抓取binlog数据_实际操作01---大数据之Nifi工作笔记0040
查看>>
NIFI从MySql中增量同步数据_通过Mysql的binlog功能_实时同步mysql数据_配置数据路由_实现数据插入数据到目标数据库_实际操作03---大数据之Nifi工作笔记0042
查看>>
NIFI从MySql中增量同步数据_通过Mysql的binlog功能_实时同步mysql数据_配置数据路由_生成插入Sql语句_实际操作02---大数据之Nifi工作笔记0041
查看>>
NIFI从MySql中离线读取数据再导入到MySql中_03_来吧用NIFI实现_数据分页获取功能---大数据之Nifi工作笔记0038
查看>>
NIFI从MySql中离线读取数据再导入到MySql中_不带分页处理_01_QueryDatabaseTable获取数据_原0036---大数据之Nifi工作笔记0064
查看>>
NIFI从MySql中离线读取数据再导入到MySql中_无分页功能_02_转换数据_分割数据_提取JSON数据_替换拼接SQL_添加分页---大数据之Nifi工作笔记0037
查看>>
NIFI从Oracle11G同步数据到Mysql_亲测可用_解决数据重复_数据跟源表不一致的问题---大数据之Nifi工作笔记0065
查看>>
NIFI从PostGresql中离线读取数据再导入到MySql中_带有数据分页获取功能_不带分页不能用_NIFI资料太少了---大数据之Nifi工作笔记0039
查看>>
nifi使用过程-常见问题-以及入门总结---大数据之Nifi工作笔记0012
查看>>