前言: 在编程的世界里,数据结构的选择往往决定了程序的效率和稳定性。而在C++的STL(Standard Template Library)库中,map和set无疑是两颗璀璨的瑰宝。它们以其独特的数据存储和检索方式,为我们提供了高效且有序的键值对存储和集合管理方案
map
和set
不仅拥有自动排序的特性,还提供了丰富的成员函数和迭代器接口,使得我们可以轻松地对其进行操作和管理。无论是在算法竞赛中,还是在日常编程中,它们都是不可或缺的工具
我们将从map和set的定义和特性开始,介绍它们的基本用法和常用成员函数。接着,我们将通过示例代码,展示如何在实际编程中使用它们。同时,我们还将探讨一些常见的错误用法和注意事项,帮助你避免在使用map和set时遇到坑
让我们一起踏上学习 map
与set
的旅程,探索它带来的无尽可能!
在初阶阶段,我们已经接触过STL中的部分容器,比如:vector、list、deque、 forward_list(C++11)等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身
关联式容器(Associative Containers) 是C++标准模板库(STL)中的一类重要容器,主要用于存储和快速检索键值对(key-value pairs)形式的数据。这类容器与序列式容器(如vector、deque、list)的主要区别在于,关联式容器中的元素是按照特定的排序准则(通常是键的大小)进行排序的,从而允许通过键来快速查找、插入和删除元素
关联式容器: 也是用来存储数据的,与序列式容器不同的是,其里面存储的是<key, value>结构的键值对,在数据检索时比序列式容器效率更高
概念: 用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息,比如我们上一篇所提到的kv模型结构 存在对应关系
SGI-STL中关于键值对的定义:(示例)
根据应用场景的不桶,STL总共实现了两种不同结构的管理式容器:树型结构与哈希结构。
关联式容器是C++ STL中一类重要的容器,它们通过键值对的形式存储数据,并支持快速的查找、插入和删除操作。常见的关联式容器包括set、multiset、map和multimap等,它们在不同的应用场景下提供了高效的解决方案
概念: set 是 C++ 标准模板库 (STL) 中的一个关联式容器,它包含的元素是唯一的,且默认情况下元素会按照升序排序。set 的内部实现通常使用红黑树来保持其有序性和唯一性
特征:
概念:multiset
是 C++ 标准库 中的一个容器,它允许存储重复的元素。与 set
不同,set
中的元素是唯一的,而 multiset
中的元素可以重复
它与
set
唯一不同的一点就是multiset
中的元素可以重复
简单演示一下差别
函数声明 | 功能介绍 |
---|---|
set (const Compare& comp = Compare(), const Allocator&= Allocator() ) | 构造空的set |
set (InputIterator first, InputIterator last, constCompare& comp = Compare(), const Allocator& =Allocator() ) | 用[first, last)区间中的元素构造set |
set ( const set<Key,Compare,Allocator>& x) | set的拷贝构造 |
构造代码实现(示例):
set的迭代器有点多,其中包括正向迭代器,反向迭代器;const迭代器与非const迭代器
函数声明 | 功能介绍 |
---|---|
iterator begin() | 返回set中起始位置元素的迭代器 |
iterator end() | 返回set中最后一个元素后面的迭代器 |
const_iterator cbegin() const | 返回set中起始位置元素的const迭代器 |
const_iterator cend() | const 返回set中最后一个元素后面的const迭代器 |
reverse_iterator rbegin() | 返回set第一个元素的反向迭代器,即end |
reverse_iterator rend() | 返回set最后一个元素下一个位置的反向迭代器,即rbegin |
const_reverse_iterator crbegin() const | 返回set第一个元素的反向const迭代器,即cend |
const_reverse_iterator crend() const | 返回set最后一个元素下一个位置的反向const迭代器,即crbegin |
因而有迭代器的存在,set可以跟方便的遍历整个结构
迭代器实现(示例):
函数声明 | 功能介绍 |
---|---|
pair<iterator,bool> insert (const value_type& x ) | 在set中插入元素x,实际插入的是<x, x>构成的键值对,如果插入成功,返回<该元素在set中的位置,true>,如果插入失败,说明x在set中已经存在,返回<x在set中的位置,false> |
void erase ( iterator position ) | 删除set中position位置上的元素 |
size_type erase ( const key_type& x ) | 删除set中值为x的元素,返回删除的元素的个数 |
void erase ( iterator first,iterator last ) | 删除set中[first, last)区间中的元素 |
void swap (set<Key,Compare,Allocator>&st ); | 交换set中的元素 |
void clear ( ) | 将set中的元素清空 |
iterator find ( const key_type& x ) const | 返回set中值为x的元素的位置 |
size_type count ( const key_type& x ) | const 返回set中值为x的元素的个数 |
在set的这些函数中,用的最多的就是insert,find,erase
首先
insert
一般是直接插入元素,或者是一段迭代器区间,在直接插入一个元素时,它的返回值是pair
first
返回新位置的迭代器,然后second
返回true
;first
返回已有元素位置的迭代器,然后second
返回false
find
不用多说,在set
中是找到则返回该位置迭代器multiset
中是返回第一个该元素位置的迭代器erase
在set中主要的作用就是删除该迭代器位置的元素,或者删除迭代器区间
multiset
的,multiset
可以有重复元素,因此可以返回删除元素的个数
这里介绍两个没有见过的函数
upper_bound,lower_bound
这两个函数通常可以和erase结合使用删除一段迭代器区间
概念: map
是 C++ 标准库中的一个关联容器,它存储的元素都是键值对(key-value pairs),并且键(key)是唯一的。在map
中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map
的内部,key与value通过成员类型value_type
绑定在一起,为其取别名称为pair
:
map
支持下标访问符,即在[]
中放入key,就可以找到与key对应的valuemap
通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))概念: multimap
是 C++ 标准库 中的一个关联容器,它允许存储具有相同键的多个值。与 map
不同,map
中的键是唯一的,而 multimap
中的键可以重复
multimap中的接口可以参考map,功能都是类似的。
注意:
operator[]
操作函数声明 | 功能介绍 |
---|---|
map() | 构造一个空的map |
函数声明 | 功能介绍 |
---|---|
begin()和end() | begin:首元素的位置,end最后一个元素的下一个位置 |
cbegin()和cend() | 与begin和end意义相同,但cbegin和cend所指向的元素不能修改 |
rbegin()和rend() | 反向迭代器,rbegin在end位置,rend在begin位置,其++和–操作与begin和end操作移动相反 |
crbegin()和crend() | 与rbegin和rend位置相同,操作相同,但crbegin和crend所指向的元素不能修改 |
函数声明 | 功能简介 |
---|---|
pair<iterator,bool> insert (const value_type& x ) | 在map中插入键值对x,注意x是一个键值对,返回值也是键值对:iterator代表新插入元素的位置,bool代表释放插入成功 |
size_type erase ( constkey_type& x ) | 删除键值为x的元素 |
void erase ( iterator first,iterator last ) | 删除[first, last)区间中的元素 |
iterator find ( const key_type& x) | 在map中插入key为x的元素,找到返回该元素的位置的迭代器,否则返回end |
const_iterator find ( const key_type& x ) const | 在map中插入key为x的元素,找到返回该元素的位置的const迭代器,否则返回cend |
mapped_type& operator[ ] (constkey_type& k) | 返回去key对应的value |
insert
在insert
插入中,所需要的元素类型是value_type
- > pair
map的成员类型
pair
可以支持带参构造,无参构造和拷贝构造
map插入代码演示:
而一般我们并不会这没写,因为有make_pair
的存在,我们往往使用make_pair
make_pair
是一个函数模板,他可以自己推演类型
operator[ ]
insert
:插入成功 pair<新插入key所在节点的iterator, true>插入失败 pair<已经存在的key所在节点的iterator,false>
在使用operator[ ]时,它会自动插入一个元素,在插入成功时,返回该位置的second
(默认为0),在插入失败时,它就会返回已有位置的second
这里推荐两个题目让大家巩固set与map 前K个高频单词 两个数组的交集
随着我们深入探讨STL(Standard Template Library)中的map和set,我们不难发现,这两个容器类型在C++编程中扮演着举足轻重的角色。它们不仅提供了高效的数据存储和检索机制,还通过其独特的性质解决了许多实际问题
在学习的过程中,我们领略了
map
如何以键值对的形式存储数据,并通过键来快速检索值。而set
则以其独特的元素唯一性特点,为我们提供了一种确保集合中元素不重复的方法,然而学习之路永无止境。对于map
和set
的理解和应用,仅仅停留在基本的使用层面是远远不够的。我们需要进一步探索它们的高级用法
学习STL中的容器并不仅仅是为了掌握它们的使用方法。更重要的是,我们要学会如何根据问题的需求选择合适的容器类型,以及如何优化我们的代码以提高程序的性能和可维护性。在这个过程中,我们将会逐渐领悟到编程的精髓和乐趣,让我们一起在学习的道路上不断前行!
希望本文能够为你提供有益的参考和启示,让我们一起在编程的道路上不断前行! 谢谢大家支持本篇到这里就结束了,祝大家天天开心!