容器库(7)-std::map

std::map是一种有序关联容器,它包含具有唯一键的键值对。搜索、移除和插入的时间复杂度是 O(logn)。底层通常是以红黑树实现的。

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

本文章的代码库:

https://gitee.com/gamestorm577/CppStd

成员函数

构造、析构和赋值

构造函数

可以用迭代器、另一个map或者元素列表来构造一个map。代码示例:

std::map<int, float> m1;
m1[1] = 1.1f;
m1[2] = 2.1f;
m1[3] = 3.1f;
std::map<int, float> m2(m1.begin(), std::next(m1.begin(), 1));
std::map<int, float> m3(m2);
std::map<int, float> tmp(m1);
std::map<int, float> m4(std::move(tmp));
std::map<int, float> m5{{1, 1.5f}, {2, 2.5f}};std::cout << "m1 size = " << m1.size() << std::endl;
std::cout << "m2 size = " << m2.size() << std::endl;
std::cout << "m3 size = " << m3.size() << std::endl;
std::cout << "m4 size = " << m4.size() << std::endl;
std::cout << "m5 size = " << m5.size() << std::endl;

输出结果:

m1 size = 3
m2 size = 1
m3 size = 1
m4 size = 3
m5 size = 2

析构函数

销毁map时会调用各元素的析构函数。代码示例:

struct MyStruct
{MyStruct(int i): Index(i){}~MyStruct(){std::cout << "destruct, Index = " << Index << std::endl;}int Index = 0;
};std::map<int, MyStruct> m = {{1, 15}, {2, 25}};
std::cout << "end" << std::endl;

输出结果:

destruct, Index = 25
destruct, Index = 15
end
destruct, Index = 25
destruct, Index = 15

赋值函数

可以用另一个map或者元素列表给map赋值。代码示例:

std::map<int, float> tmp{{1, 1.1f}, {2, 1.2f}, {3, 1.3f}};
std::map<int, float> m1;
std::map<int, float> m2;m1 = tmp;
m2 = {{1, 1.1f}, {2, 1.2f}};
std::cout << "m1 size = " << m1.size() << std::endl;
std::cout << "m2 size = " << m2.size() << std::endl;

输出结果:

m1 size = 3
m2 size = 2

元素访问

at

返回指定key值的value值的引用,如果没有该key值,会抛出异常。代码示例:

std::map<int, float> m{{1, 1.1f}, {2, 1.2f}, {3, 1.3f}};
m.at(2) = 20.5f;
std::cout << "m key 2 = " << m.at(2) << std::endl;

输出结果:

m key 2 = 20.5

operator[]

返回指定key值的value值的引用,如果该没有key值,会插入该key值。代码示例:

std::map<int, float> m{{1, 1.1f}, {2, 1.2f}, {3, 1.3f}};
std::cout << "m key 2 = " << m[2] << std::endl;
std::cout << "m key 20 = " << m[20] << std::endl;

输出结果:

m key 2 = 1.2
m key 20 = 0

迭代器

接口begin、cbegin指向map起始的迭代器,end、cend指向末尾的迭代器。rbegin、crbegin指向起始的逆向迭代器,rend、crend指向末尾的逆向迭代器。代码示例:

std::map<int, float> m{{5, 1.1f}, {17, 1.2f}, {19, 1.3f}};
for (auto iter = m.begin(); iter != m.end(); ++iter)
{iter->second += 20.f;
}for (auto iter = m.cbegin(); iter != m.cend(); ++iter)
{std::cout << "key " << iter->first << " value = " << iter->second<< std::endl;
}

输出结果:

key 5 value = 21.1
key 17 value = 21.2
key 19 value = 21.3

容量

empty

检查map是否为空。代码示例:

std::map<int, float> m;
std::cout << std::boolalpha;
std::cout << "m empty: " << m.empty() << std::endl;
m[15] = 15.5f;
std::cout << "m empty: " << m.empty() << std::endl;

输出结果: 

m empty: true
m empty: false

size

获取元素的个数。代码示例:

std::map<int, float> m1;
std::map<int, float> m2{{1, 1.1f}, {2, 1.2f}, {3, 1.3f}};
std::cout << "m1 size = " << m1.size() << std::endl;
std::cout << "m2 size = " << m2.size() << std::endl;

输出结果:

m1 size = 0
m2 size = 3

max_size

返回可以容纳的对答元素数。代码示例:

std::map<int, int> m1;
std::map<double, double> m2;
std::cout << "m1 max_size = " << m1.max_size() << std::endl;
std::cout << "m2 max_size = " << m2.max_size() << std::endl;

可能的输出结果:

m1 max_size = 461168601842738790
m2 max_size = 384307168202282325

修改器

clear

清除所有的元素。代码示例:

std::map<int, float> m{{1, 1.1f}, {2, 1.2f}, {3, 1.3f}};
std::cout << "m size = " << m.size() << std::endl;
m.clear();
std::cout << "m size = " << m.size() << std::endl;

输出结果:

m size = 3
m size = 0

insert

插入元素,参数可以是元素、迭代器或者元素节点。如果插入的key值已经存在,那么该key值不会被插入,对应的value值也不会修改。代码示例:

std::cout << std::boolalpha;
std::map<int, float> m;auto [item1, ret1] = m.insert({1, 12.5f});
std::cout << "ret1 = " << ret1 << std::endl;
auto [item2, ret2] = m.insert(*item1);
std::cout << "ret2 = " << ret2 << std::endl;
auto [item3, ret3] = m.insert({1, 15.5f});
std::cout << "ret3 = " << ret3 << std::endl;
std::cout << "m size = " << m.size() << std::endl;
std::cout << "m key 1 = " << m.at(1) << std::endl;std::map<int, float> tmp{{1, 1.1f}, {2, 1.2f}, {3, 1.3f}};
m.insert(tmp.begin(), tmp.end());
std::cout << "m size = " << m.size() << std::endl;
std::cout << "m key 1 = " << m.at(1) << std::endl;

输出结果:

ret1 = true
ret2 = false
ret3 = false
m size = 1
m key 1 = 12.5
m size = 3
m key 1 = 12.5

insert_or_assign

插入一对键值,如果key已经存在,对应的value将被新的值替换。代码示例:

std::map<int, float> m;
m.insert_or_assign(5, 17.3f);
std::cout << "m key 5 = " << m.at(5) << std::endl;
m.insert_or_assign(5, 35.4f);
std::cout << "m key 5 = " << m.at(5) << std::endl;

输出结果:

m key 5 = 17.3
m key 5 = 35.4

emplace

构造一对键值到map中。如果key值已经存在,将不会对map做任何修改。代码示例:

struct MyStruct
{MyStruct(const std::string& str, double num): Str(str), Num(num){}std::string Str;double Num;
};std::map<int, MyStruct> m;
std::cout << "m size = " << m.size() << std::endl;
m.emplace(5, MyStruct{"a", 1.3});
std::cout << "m size = " << m.size() << std::endl;
m.emplace(5, MyStruct{"b", 2.3});
std::cout << "m size = " << m.size() << std::endl;
m.emplace(25, MyStruct{"a", 1.3});
std::cout << "m size = " << m.size() << std::endl;
std::cout << "m key 5 is: " << m.at(5).Num << std::endl;

输出结果:

m size = 0
m size = 1
m size = 1
m size = 2
m key 5 is: 1.3

emplace_hint

向map中尽可能靠近hint之前的位置插入新元素。

template <class ..._Args>
iterator emplace_hint(const_iterator hint, _Args&&... args)

不同的hint会导致插入元素的效率不同。代码示例:

auto timer = [](std::function<std::size_t()> func, std::string tag) -> void
{auto start = std::chrono::system_clock::now();std::size_t size = func();auto end = std::chrono::system_clock::now();std::chrono::duration<double, std::milli> time = end - start;std::cout << tag << ", size: " << size << ", use time: " << time.count()<< std::endl;
};const int count = 1000000;auto map_emplace = [=]() -> std::size_t
{std::map<int, char> m;for (int i = 0; i < count; ++i){m.emplace(i, 'a');}return m.size();
};auto map_emplace_hint1 = [=]() -> std::size_t
{std::map<int, char> m;auto iter = m.begin();for (int i = 0; i < count; ++i){m.emplace_hint(iter, i, 'a');iter = m.end();}return m.size();
};auto map_emplace_hint2 = [=]() -> std::size_t
{std::map<int, char> m;auto iter = m.begin();for (int i = 0; i < count; ++i){m.emplace_hint(iter, i, 'a');iter = m.begin();}return m.size();
};auto map_emplace_hint3 = [=]() -> std::size_t
{std::map<int, char> m;auto iter = m.begin();for (int i = 0; i < count; ++i){iter = m.emplace_hint(iter, i, 'a');}return m.size();
};timer(map_emplace, "map_emplace");
timer(map_emplace_hint1, "map_emplace_hint1");
timer(map_emplace_hint2, "map_emplace_hint2");
timer(map_emplace_hint3, "map_emplace_hint3");

可能的输出结果:

map_emplace, size: 1000000, use time: 620.713
map_emplace_hint1, size: 1000000, use time: 260.807
map_emplace_hint2, size: 1000000, use time: 693.763
map_emplace_hint3, size: 1000000, use time: 382.412

try_emplace

构造一对键值到map中。如果key值已经存在,将不会对map做任何修改。代码示例:

std::map<int, double> m;
m.emplace_hint(m.begin(), 5, 15.1);
m.emplace_hint(m.begin(), 17, 45.5);
m.emplace_hint(m.begin(), 5, 39.4);
m.emplace_hint(m.begin(), 29, 19.4);for (auto& item : m)
{std::cout << "key: " << item.first << ", value: " << item.second<< std::endl;
}

输出结果:

key: 5, value: 15.1
key: 17, value: 45.5
key: 29, value: 19.4

erase

移除指定位置或者指定key的容器。代码示例:

std::map<int, float> m{{5, 1.1f}, {7, 1.2f}, {19, 1.3f}, {29, 1.4f}};
std::cout << "m size = " << m.size() << std::endl;
m.erase(m.begin());
std::cout << "m size = " << m.size() << std::endl;
m.erase(18);
std::cout << "m size = " << m.size() << std::endl;
m.erase(19);
std::cout << "m size = " << m.size() << std::endl;

输出结果:

m size = 4
m size = 3
m size = 3
m size = 2

swap

和另一个map交换元素内容。代码示例:

std::map<int, float> m1{{5, 1.1f}, {7, 1.2f}, {19, 1.3f}, {29, 1.4f}};
std::map<int, float> m2{{15, 1.1f}, {27, 1.2f}};
m1.swap(m2);
std::cout << "m1 size = " << m1.size() << std::endl;
std::cout << "m2 size = " << m2.size() << std::endl;

输出结果:

m1 size = 2
m2 size = 4

extract

提取map中的某个元素节点,提取后map不再拥有该元素。代码示例:

std::map<int, float> m{{5, 1.1f}, {7, 1.2f}, {19, 1.3f}, {29, 1.4f}};
std::cout << "m size: " << m.size() << std::endl;
auto node = m.extract(5);
std::cout << "m size: " << m.size() << std::endl;
m.insert(std::move(node));
std::cout << "m size: " << m.size() << std::endl;

输出结果:

m size: 4
m size: 3
m size: 4

merge

合并另一个map,只插入不存在的key值。代码示例:

std::map<int, float> m1{{1, 1.1f}, {2, 1.2f}, {3, 1.3f}};
std::map<int, float> m2{{3, 50.1f}, {4, 50.2f}};
m1.merge(m2);
for (auto& item : m1)
{std::cout << "key: " << item.first << ", value: " << item.second<< std::endl;
}

输出结果:

key: 1, value: 1.1
key: 2, value: 1.2
key: 3, value: 1.3
key: 4, value: 50.2

查找

count

返回匹配key值的元素个数,结果只能是0或者1。代码示例:

std::map<int, float> m{{1, 1.1f}, {2, 1.2f}, {3, 1.3f}};
std::cout << "m key 1 count: " << m.count(1) << std::endl;
std::cout << "m key 4 count: " << m.count(4) << std::endl;

输出结果:

m key 1 count: 1
m key 4 count: 0

find

返回匹配key值的迭代器。代码示例:

std::map<int, float> m{{1, 1.1f}, {2, 1.2f}, {3, 1.3f}};
std::cout << "m key 2 value is: " << m.find(2)->second << std::endl;

输出结果:

m key 2 value is: 1.2

contains

检查是否包含某个key值,返回布尔值。代码示例:

std::map<int, float> m{{1, 1.1f}, {2, 1.2f}, {3, 1.3f}};
std::cout << std::boolalpha;
std::cout << "m contains 2: " << m.contains(2) << std::endl;
std::cout << "m contains 4: " << m.contains(4) << std::endl;

输出结果:

m contains 2: true
m contains 4: false

lower_bound

返回首个大于等于给定键值的迭代器。代码示例:

std::map<int, float> m{{1, 1.1f}, {2, 1.2f}, {3, 1.3f}};
auto iter = m.lower_bound(2);
std::cout << "key = " << iter->first << std::endl;

输出结果:

key = 2

upper_bound

返回首个大于给定键值的迭代器。代码示例:

std::map<int, float> m{{1, 1.1f}, {2, 1.2f}, {3, 1.3f}};
auto iter = m.upper_bound(2);
std::cout << "key = " << iter->first << std::endl;

输出结果:

key = 3

equal_bound

返回一对迭代器,分别是lower_bound和upper_range的结果。代码示例:

std::map<int, float> m{{1, 1.1f}, {2, 1.2f}, {3, 1.3f}};
auto [iter1, iter2] = m.equal_range(2);
std::cout << "iter1 key = " << iter1->first << std::endl;
std::cout << "iter2 key = " << iter2->first << std::endl;

输出结果:

iter1 key = 2
iter2 key = 3

观察器

key_comp

返回用于比较key值的函数。代码示例:

struct MyComp
{bool operator()(int lhs, int rhs) const{std::cout << "MyComp" << std::endl;return true;}
};std::map<int, std::string, MyComp> m;
auto comp = m.key_comp();
comp(10, 20);

输出结果:

MyComp

value_comp

返回用于比较键值对的函数,参数是键值对,但实际是比较的key值。代码示例:

struct MyComp
{bool operator()(int lhs, int rhs) const{std::cout << "MyComp" << std::endl;return true;}
};std::map<int, std::string, MyComp> m;
auto comp = m.value_comp();
comp(std::make_pair(1, "a"), std::make_pair(2, "b"));

输出结果:

MyComp

非成员函数

比较运算符

operator==,!=,<,<=,>,>=用于比较两个map。代码示例:

std::map<int, float> m1{{1, 1.1f}, {2, 1.2f}, {3, 1.3f}};
std::map<int, float> m2{{1, 1.1f}, {2, 1.2f}};
std::cout << std::boolalpha;
std::cout << "m1 == m2: " << (m1 == m2) << std::endl;
std::cout << "m1 != m2: " << (m1 != m2) << std::endl;
std::cout << "m1 <  m2: " << (m1 < m2) << std::endl;
std::cout << "m1 <= m2: " << (m1 <= m2) << std::endl;
std::cout << "m1 >  m2: " << (m1 > m2) << std::endl;
std::cout << "m1 >= m2: " << (m1 >= m2) << std::endl;

输出结果:

m1 == m2: false
m1 != m2: true
m1 <  m2: false
m1 <= m2: false
m1 >  m2: true
m1 >= m2: true

swap

交换两个map的元素内容。代码示例:

std::map<int, float> m1{{1, 1.1f}, {2, 1.2f}, {3, 1.3f}};
std::map<int, float> m2{{1, 1.1f}, {2, 1.2f}};
std::swap(m1, m2);
std::cout << "m1 size = " << m1.size() << std::endl;
std::cout << "m2 size = " << m2.size() << std::endl;

输出结果:

m1 size = 2
m2 size = 3

erase_if

删除满足要求的元素。代码示例:

std::map<int, float> m{{1, 1.1f}, {2, 1.2f}, {3, 21.3f}, {4, 21.5f}};
std::erase_if(m,[](const std::pair<int, float>& pair) -> bool{return pair.second > 10.f;});for (auto& item : m)
{std::cout << "key: " << item.first << ", value: " << item.second<< std::endl;
}

输出结果:

key: 1, value: 1.1
key: 2, value: 1.2

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/477992.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Gitlab CI/CD docker命令报错:/usr/bin/bash: line 136: docker:command not found

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

chrome版本117驱动下载路,解决版本不匹配问题

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

数字化商品管理:革新鞋服零售模式,引领智能商业新时代

随着科技的快速发展&#xff0c;数字化浪潮席卷各行各业&#xff0c;鞋服零售企业亦不例外。在这个新时代&#xff0c;数字化商品管理不仅成为鞋服零售企业革新的关键&#xff0c;更是其引领智能商业浪潮的重要引擎。本文将围绕数字化商品管理如何深刻影响鞋服零售模式&#xf…

Java 21 新特性的扫盲级别初体验

一、前言 JDK 21 于 2023 年 9 月发布&#xff0c;作为目前讨论热度最高的JDK&#xff0c;虽然大家都开玩笑说你发任你发&#xff0c;我用Java8&#xff0c;但是作为一个Javaer&#xff0c;对JDK21的新特性还是要有所了解的。 以下是 JDK 21 的新功能列表&#xff1a; 虚拟线…

Java关键字大全

概览 以上是我们学习Java从小白到入门能够接触到的关键字。 下面整理一些我们刚开始学习Java会经常用到的关键字的用法概述&#xff1a; 一、本数据类型&#xff08;4类8种&#xff09; 类型种类&#xff1a; 四类八种整型byte,short,int,long 浮点型float,double字符型cha…

GA-kmedoid 遗传算法优化K-medoids聚类

遗传算法优化K-medoids聚类是一种结合了遗传算法和K-medoids聚类算法的优化方法。遗传算法是一种基于自然选择和遗传机制的随机优化算法&#xff0c;它通过模拟生物进化过程中的遗传、交叉、变异等操作来寻找问题的最优解。而K-medoids聚类算法是一种基于划分的聚类方法&#x…

Python:常见的运算符

一、算术运算符 算术在数学中可以直接运用的一些运算规则&#xff1a; ------- 加法运算 - ------- 减法运算 * ------- 乘法运算 / ------- 除法运算 强数据类型语言中/表示的整除运算 // ------ 整除 % ------ 取余运算 ** ------ 幂次方运算 >>> a 10 >>&…

【数据结构】13:表达式转换(中缀表达式转成后缀表达式)

思想&#xff1a; 从头到尾依次读取中缀表达式里的每个对象&#xff0c;对不同对象按照不同的情况处理。 如果遇到空格&#xff0c;跳过如果遇到运算数字&#xff0c;直接输出如果遇到左括号&#xff0c;压栈如果遇到右括号&#xff0c;表示括号里的中缀表达式已经扫描完毕&a…

业务流程图与功能流程图到底有什么区别?

先介绍一下业务流程图&#xff1a; 一、业务流程图 业务流程图(Transaction Flow Diagram&#xff0c;TFD)是一种描述管理系统内各单位、人员之间的业务关系、作业顺序和管理信息流向的图表。它用一些规定的符号及连线表示某个具体业务的处理过程&#xff0c;帮助分析人员找出…

基于Spring Boot的车辆管理系统,计算机毕业设计(带源码+论文)

源码获取地址&#xff1a; 码呢-一个专注于技术分享的博客平台一个专注于技术分享的博客平台,大家以共同学习,乐于分享,拥抱开源的价值观进行学习交流http://www.xmbiao.cn/resource-details/1759578742199496705

阿基米德签证小程序管理系统功能清单

阿基米德签证小程序管理系统&#xff0c;底层架构采用当前国内最流行的php框架thinkphp8.0、采用广泛使用的MYSQL数据库&#xff0c;管理后台前后台分离&#xff0c;同时使用了当今最流行的基于VUE3和elementPlus前端框架&#xff0c;小程序采用了支持多端合一的UNI-APP开发&am…

【AI数字人-论文】AD-NeRF论文

文章目录 NeRFAD-NeRF模型NeRF体渲染个体NeRF表示背景和姿态编辑 loss 参考 NeRF 将一个连续的场景表示为一个输入为5D向量的函数&#xff0c;这个函数为NeRF函数&#xff0c;它的输入由一个空间点的3D位置 x ( x , y , z ) \mathbf{x} \left( x, y, z \right) x(x,y,z)和它…