C++——STL标准模板库——容器详解——map

一、基本概念

1、map容器是STL中的一种具备自动排序功能的关联式容器。它提供了一对一的数据处理能力(其中第一个称为关键字,相当于索引,每个关键字在map中唯一,也是排序的主要依据;第二个称为该关键字的值,可以是任意类型),维护数据的对象是pair类型的键值对。pair<Key_type,Velue_type>,键值对的键和值可以是任意类型,一般键为string类型或者int类型,方便维护。

2、pair类型叫做对组,底层是模板结构体,提供两个模板参数。也就是pair<Type1,Type2>,模板参数列表中的参数可以是任意类型。用pair<T1,T2>::first读取第一个值,pair<T1,T2>::second读取第二个值。

3、map底层结构是红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的。并且不会存在重复关键字。

4、multimap和map具备同样的功能,但允许容器内出现重复关键字。

二、构造函数

1、map<T1,T2> m; 默认构造函数

2、map<T1,T2> m(iterator first,iterator last); 区间构造函数,需要提供存储键值对的容器迭代器

3、map<T1,T2> m(map<T1,T2>& other); 复制构造函数

4、map<T1,T2> m(map<T1,T2>& other); 移动构造函数

5、map<T1,T2> m(initializer_list& _list); 初始化列表构造函数

6、map<T1,T2,Key_Compare> m; 自定义排序方式构造函数

map和set一样通过模板参数列表自定义排序方式。编译器默认内置数据类型例如int、double、string均为递增排序,需要递减排序或者关键字为自定义数据时,必须添加自定义排序类型。同样提供了多种重载,需根据实际情况灵活选用。

三、成员函数

(一)迭代器相关函数

1、iterator map<T1,T2>::begin(); 返回容器第一个元素位置迭代器

2、iterator map<T1,T2>::end(); 返回容器最后一个元素后面一个位置的迭代器

3、iterator map<T1,T2>::rbegin(); 返回最后一个元素位置迭代器

4、iterator map<T1,T2>::rend(); 返回第一个元素前面一个位置的迭代器

cbegin()、cend()、crbegin()、crend() 分别返回以上4种的常量迭代器

(二)大小相关函数

1、size_t map<T1,T2>::size(); 返回容器当前元素数量

2、size_t map<T1,T2>::max_size(); 返回容器理论上最大容纳元素数量

3、bool map<T1,T2>::empty(); 判断容器是否为空

(三)访问函数

1、const T2& map<T1,T2>::at(const T1&key); 返回索引key对应元素的常引用

2、T2& map<T1,T2>::at(const T1&key); 返回索引key对应元素的引用

3、T2& map<T1,T2>::operator[](const T1&key) 下标符号[]重载,返回索引对应元素引用

以上3种访问函数传入参数均为关键字,而不是下标。当容器中关键字不存在时会出现出界问题。所以在使用前务必确认map容器中存在关键字,才可作为索引值传入。

(四)插入函数

插入元素必须为键值对,同样map元素调用插入函数,返回了对组<iterator,bool>,multimap调用插入函数返回迭代器iterator

1、insert(const pair<T1,T2>&value); 复制插入

例1 insert(pair<T1,T2>(T1_value,T2_value);

例2 insert(make_pair(T1_value,T2_value);

例3 insert(map<T1,T2>::value_type(T1value,T2_value);

2、insert(iterator pos,const pair<T1,T2>&value); 指定位置插入,其实指定位置没用,返回的迭代器还是指向排序后该元素的位置。

3、inset(initializer _list); 插入初始化列表,这个列表是pair类型的列表

4、insert(itrator first,itertor last); 插入区间,提供的迭代器必须是储存相同pair类型的容器迭代器

5、insert(const pair<T1,T2>&&value); 移动插入只移动关键字,不移动值

6、emplace(pair<T1,T2>&&value); 在容器内构造元素

7、map<T1,T2>::operator[](key); 此方法不稳定,当map容器内不存在关键字key时,会自动添加该关键字的键值对。

(五)删除函数

1、size_t map<T1,T2>::erase(const T1&key); 按关键字删除元素,返回删除数量;

2、iterator map<T1,T2>::erase(const_iterator&where); 删除指定位置元素,返回该位置迭代器

3、iterator map<T1,T2>::erase(iterator first,iterator last); 按区间删除元素,返回起始位置迭代器

4、void map<T1,T2>::clear() 清空容器

(六)查找函数

1、iterator map<T1,T2>::find(const T1&key); 查找关键字,返回迭代器

2、size_t map<T1,T2>::count(const T1&key); 返回给定关键字的数量,map容器一般返回1或0

3、iterator map<T1,T2>::lower_bound(const T1&key);

iterator map<T1,T2>::upper_bound(const T1&key);

和set容器一样,都是返回指向拟插入key位置的迭代器,lower向左寻找,upper向右寻找。举例说明:

map中有关键字序列:1,3,5,7,9 m.lower_bound(4);返回迭代器指向5,m.upper_bound(4)也指向5,因为map中关键字具有唯一性;m.lower_bound(3);指向3,m.upper_bound(3)指向5。

multimap有关键字序列:9,7,5,5,5,3,3,1 m.lower_bound(3)指向第一个3,m.upper_bound(3)指向1;m.lower_bound(5)指向第一个5,m.upper_bound(5)指向第一个3。

5、pair<it,it> map<T1,T2>::equal_range(const T1&key); 返回给定关键字以内的区间

四、使用注意事项

(一)优点

1、数据结构采用红黑树,自身是有序的,插入数据时会自动排序。

2、内部结构采用红黑树,时间复杂度低,效率高。

3、索引方便,可以通过下标key方便的进行存取。

4、所有元素都会根据元素的键值自动排序。

5、不能通过map的迭代器改变键值。因为键值关系搞map元素的排列规则,任意改变map键值,将会严重破坏map组织,修改元素的实值是可以的。

6、在对容器元素进行新增或删除操作时,操作之前的所有迭代器,在操作完成后,依然有效;被删除的那个元素的迭代器无效。

(二)缺点

1、map内部采用红黑数实现,需要额外空间保存节点,会占用多余的空间,典型的以"空间换时间"。

2、使用at()索引时,要确定容器内存在传入的关键字,否则会抛出异常;使用[]索引时,如果容器内没有传入关键字,容器会自动添加改关键字的键值对。

(三)使用注意事项

1、map容器中的元素是pair类型,每个元素包含两个部分:键(key)和值(value)。键是唯一的,而值可以是重复的。在map中不能插入具有相同键的元素。若需要插入相同键的元素,可以使用multimap。

2、map容器的迭代器是双向的,这意味着在遍历过程中删除元素可能会导致未定义的行为。因此,在遍历过程中不应该删除元素。如果需要在遍历过程中删除元素,可以先将需要删除的元素保存下来,遍历完成后再进行删除。

3、map容器中的元素是按照键的顺序进行排序的,因此在使用map容器时需要注意键的类型和比较函数。如果需要自定义比较函数,可以使用map容器的比较函数适配器进行设置。

4、map容器的查找操作的时间复杂度为O(log n),其中n是map容器中元素的数量。因此,在处理大量数据时,使用map容器可以提高查找效率。但是需要注意的是,由于map容器需要维护元素的顺序,因此在插入和删除元素时可能会比其他容器慢一些。

5、map容器可以用于存储不同类型的元素,例如int和string等。在使用不同类型的元素时需要注意数据的兼容性和比较函数的设置。

相关推荐
蜀黍@猿几秒前
C/C++基础错题归纳
c++
古希腊掌管学习的神8 分钟前
[LeetCode-Python版]相向双指针——611. 有效三角形的个数
开发语言·python·leetcode
赵钰老师9 分钟前
【R语言遥感技术】“R+遥感”的水环境综合评价方法
开发语言·数据分析·r语言
雨中rain15 分钟前
Linux -- 从抢票逻辑理解线程互斥
linux·运维·c++
就爱学编程17 分钟前
重生之我在异世界学编程之C语言小项目:通讯录
c语言·开发语言·数据结构·算法
Oneforlove_twoforjob40 分钟前
【Java基础面试题025】什么是Java的Integer缓存池?
java·开发语言·缓存
emoji11111141 分钟前
前端对页面数据进行缓存
开发语言·前端·javascript
每天都要学信号1 小时前
Python(第一天)
开发语言·python
TENET信条1 小时前
day53 第十一章:图论part04
开发语言·c#·图论
生信圆桌1 小时前
【生信圆桌x教程系列】如何安装 seurat V5版本R包,最详细安装手册
开发语言·r语言