C++:stl中set(multiset)和map(multimap)的介绍和使用

news2024/9/22 17:17:43

本文主要从概念、常用接口和使用方法方面介绍set(multiset)和map(multimap)。

目录

一、概念介绍

1.关联式容器

2.键值对

3. 树形结构的关联式容器

二、set和multiset

1.set的介绍

2.set使用

1. set模板参数列表

2. set构造

3. set迭代器

4. set容量

5. set修改操作

6.set使用举例

3.multiset介绍

4.multiset的使用

三、map和multimap

1.map的介绍

2.map的使用

1. map模板参数说明

2. map构造

3. map的迭代器

4. map的容量与元素访问

5. map中元素的修改

6.使用举例

3.multimap的介绍

4.multimap的使用


一、概念介绍

1.关联式容器

在前面的文章中,介绍了一些容器,比如:vector、list、deque等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身。

关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是<key,value>结构的键值对,在数据检索时比序列式容器效率更高。

2.键值对

键值对是用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息。

比如:现在要建立一个英汉互译的字典,那该字典中必然有英文单词与其对应的中文含义,而且,英文单词与其中文含义是一一对应的关系,即通过单词,在词典中就可以找到与其对应的中文含义。

SGI-STL中关于键值对的定义:

template <class T1, class T2>
struct pair
{
	typedef T1 first_type;
	typedef T2 second_type;
	T1 first;
	T2 second;
	pair() : first(T1()), second(T2())
	{}
	pair(const T1& a, const T2& b) : first(a), second(b)
	{}
};

3. 树形结构的关联式容器

根据应用场景的不同,STL总共实现了两种不同结构的管理式容器:树型结构与哈希结构。树型结 构的关联式容器主要有四种:map、set、multimap、multiset。这四种容器的共同点是:使用平衡搜索树(即红黑树)作为其底层结果,容器中的元素是一个有序的序列。

二、set和multiset

set文档介绍

1.set的介绍

1.set是按照一定次序存储元素的容器

2. 在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的。set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。

3. 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行排序。

4. set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对子集进行直接迭代。

5. set在底层是用二叉搜索树(红黑树)实现的。

注意:

1. 与map/multimap不同,map/multimap中存储的是真正的键值对,set中只放value,但在底层实际存放的是由<value,value>构成的键值对。

2. set中插入元素时,只需要插入value即可,不需要构造键值对。

3. set中的元素不可以重复(因此可以使用set进行去重)。

4. 使用set的迭代器遍历set中的元素,可以得到有序序列

5. set中的元素默认按照小于来比较

6. set中查找某个元素,时间复杂度为:\log_{2}N

7. set中的元素不允许修改

8. set中的底层使用二叉搜索树(红黑树)来实现。

2.set使用

1. set模板参数列表

T :  set中存放元素的类型,实际在底层存储的键值对。

Compare:set中元素默认按照小于来比较

Alloc:set中元素空间的管理方式,使用STL提供的空间配置器管理

2. set构造

函数声明功能介绍
set (const Compare& comp = Compare(), const Allocator& = Allocator() );构造空的set
set (InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator() );用[first, last)区 间中的元素构造 set
set ( const set<Key,Compare,Allocator>& x);set的拷贝构造

例:

set<string> s1; //构造一个string类型的空set

string str = "hello world";
set<char> s2(str.begin(),str.end()); 
//用[str.begin(), str.end())区间中的元素构造set

set<string> s3(s1); //拷贝构造

3. set迭代器

函数声明功能介绍
iterator begin()返回set中起始位置元素的迭代器
iterator end()返回set中最后一个元素后面的迭代器
reverse_iterator rbegin()返回set第一个元素的反向迭代器,即end
reverse_iterator rend()返回set最后一个元素下一个位置的反向迭代器, 即rbegin

下表为依次对应的const迭代器:

const_iterator cbegin() const返回set中起始位置元素的const迭代器
const_iterator cend() const返回set中最后一个元素后面的const迭代器
const_reverse_iterator crbegin() const返回set第一个元素的反向const迭代器,即cend
const_reverse_iterator crend() const返回set最后一个元素下一个位置的反向const迭 代器,即crbegin

4. set容量

函数声明功能介绍
bool empty ( ) const检测set是否为空,空返回true,否则返回true
size_type size() const返回set中有效元素的个数

5. 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的元素的个数

6.set使用举例

void TestSet()
{
    // 用数组array中的元素构造set
    int array[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0, 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };

    set<int> s(array, array + sizeof(array) / sizeof(array[0]));

    cout << s.size() << endl; //10

    // 正向打印set中的元素,从打印结果中可以看出:set可去重
    for (auto& e : s)
        cout << e << " ";  //0 1 2 3 4 5 6 7 8 9
    cout << endl;

    //删除元素8
    s.erase(8);
    //查找元素9,删除
    set<int>::iterator ptr = s.find(9); 
    if (ptr != s.end())
    {
        s.erase(ptr);
    }

    // 使用迭代器逆向打印set中的元素
    for (auto it = s.rbegin(); it != s.rend(); ++it)
        cout << *it << " ";   //7 6 5 4 3 2 1 0
    cout << endl;

    // set中值为3的元素出现了几次
    cout << s.count(3) << endl; // 1
}

3.multiset介绍

multiset文档介绍

1. multiset是按照特定顺序存储元素的容器,其中元素是可以重复的。

2. 在multiset中,元素的value也会识别它(因为multiset中本身存储的就是<value, value>组成的键值对,因此value本身就是key,key就是value,类型为T)。 multiset元素的值不能在容器中进行修改(因为元素总是const的),但可以从容器中插入或删除。

3. 在内部,multiset中的元素总是按照其内部比较规则(类型比较)所指示的特定严格弱排序准则进行排序。

4. multiset容器通过key访问单个元素的速度通常比unordered_multiset容器慢,但当使用迭代器遍历时会得到一个有序序列。

5. multiset底层结构为二叉搜索树(红黑树)。

注意:

1. multiset中再底层中存储的是<value, value>的键值对

2. multiset的插入接口中只需要插入即可

3. 与set的区别是,multiset中的元素可以重复,set是中value是唯一的

4. 使用迭代器对multiset中的元素进行遍历,可以得到有序的序列

5. multiset中的元素不能修改

6. 在multiset中找某个元素,时间复杂度为$O(log_2 N)$

7. multiset的作用:可以对元素进行排序

4.multiset的使用

此处只简单演示set与multiset的不同,其他接口接口与set相同,可以参考set。

void TestSet()
{
    int array[] = { 2, 1,4,4,3,9,6,8,8,8 };

    // 注意:multiset在底层实际存储的是<int, int>的键值对
    multiset<int> s(array, array + sizeof(array) / sizeof(array[0]));
    for (auto& e : s)
        cout << e << " "; //1 2 3 4 4 6 8 8 8 9
    cout << endl;

    // set中没有重复元素,元素存在count返回1,不在返回0
    // multiset可以返回重复元素的个数
    cout << s.count(8) << endl; // 3
}

三、map和multimap

1.map的介绍

map的文档简介

1. map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元 素。

2. 在map中,键值key通常用于排序和唯一的标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型 value_type绑定在一起,为其取别名称为 pair:typedef pair<const key, T> value_type;

3. 在内部,map中的元素总是按照键值key进行比较排序的。

4. map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)。

5. map支持下标访问符,即在[]中放入key,就可以找到与key对应的value。

6. map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))。

2.map的使用

1. map模板参数说明

key: 键值对中key的类型

T: 键值对中value的类型

Compare: 比较器的类型,map中的元素是按照key来比较的,缺省情况下按照小于来比较,一般情况下(内置类型元素)该参数不需要传递,如果无法比较时(自定义类型),需要用户自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递)

Alloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的空间配置器

注意:在使用map时,需要包含头文件。

map (const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type());

2. map构造

函数声明功能介绍
map (const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type());构造空的set
map (InputIterator first, InputIterator last, const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type());用[first, last)区 间中的元素构造map
map (const map& x);map的拷贝构造
map <string,int> m1; //构造一个key为string类型,value为int类型的空map

map<string, int> m2(m1.begin(), m1.end());
//用[m1.begin(), m2.end())区间中的元素构造map

map<string,int> m3(m2); //拷贝构造

3. 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所 指向的元素不能修改

4. map的容量与元素访问

函数声明功能简介
bool empty ( ) const检测map中的元素是否为空,是返回 true,否则返回false
size_type size() const返回map中有效元素的个数
mapped_type& operator[] (const key_type& k)返回去key对应的value

注意:

在元素访问时,有一个与operator[]类似的操作at()(该函数不常用)函数,都是通过key找到与key对应的value然后返回其引用,不同的是:当key不存在时,operator[]用默认value与key构造键值对然后插入,返回该默认value,at()函数直接抛异常。

5. map中元素的修改

函数声明功能简介
pair<iterator,bool> insert ( const value_type& x )在map中插入键值对x,注意x是一个键值对,返回值也是键值对:iterator代表新插入元素的位置,bool代表释放插入成功
void erase ( iterator position )删除position位置上的元素
size_type erase ( const key_type& x )删除键值为x的元素
void erase ( iterator first, iterator last )删除[first, last)区间中的元素
void swap ( map<Key,T,Compare,Allocator>& mp )交换两个map中的元素
void clear ( )将map中的元素清空
iterator find ( const key_type& x )在map中插入key为x的元素,找到返回该元素的位置的迭代器,否则返回end
const_iterator find ( const key_type& x ) const在map中插入key为x的元素,找到返回该元素的位置的const迭代器,否则返回cend
size_type count ( const key_type& x ) const返回key为x的键值在map中的个数,注意 map中key是唯一的,因此该函数的返回值要么为0,要么为1,因此也可以用该函数来检测一个key是否在map中

6.使用举例

void TestMap()
{
    map<string, string> m;

    // 向map中插入元素的方式:
    // 1.将键值对<"red","红色">插入map中,用pair直接来构造键值对
    m.insert(pair<string, string>("red", "红色"));

    // 2.将键值对<yellow", "黄色">插入map中,用make_pair函数来构造键值对
    m.insert(make_pair("yellow", "黄色"));


    // 3.借用operator[]向map中插入元素
/*
    operator[]的原理是:
     用<key, T()>构造一个键值对,然后调用insert()函数将该键值对插入到map中
     如果key已经存在,插入失败,insert函数返回该key所在位置的迭代器
     如果key不存在,插入成功,insert函数返回新插入元素所在位置的迭代器
     operator[]函数最后将insert返回值键值对中的value返回
*/
    // 将<"green", "">插入map中,插入成功,返回value的引用,将“绿色”赋值给该引用结果
    m["green"] = "绿色";

    // key不存在时抛异常
    //m.at("pink") = "粉色";
    cout << m.size() << endl;  // 3


    // 用迭代器去遍历map中的元素,可以得到一个按照key排序的序列
    for (auto& e : m)
        cout << e.first << "-->" << e.second << endl; //green-->绿色
    cout << endl;                                     //red-- > 红色
                                                      //yellow-- > 黄色
    

    // map中的键值对key一定是唯一的,如果key存在将插入失败
    //insert返回类型auto为pair<iterator,bool>
    auto ret = m.insert(make_pair("red", "红色"));
    if (ret.second)
        cout << "<red, 红色>不在map中, 已经插入" << endl;
    else
        cout << "键值为red的元素已经存在:" << ret.first->first << "-->"
        << ret.first->second << " 插入失败" << endl;


    // 删除key为"red"的元素
    m.erase("green");
    if (1 == m.count("green"))
        cout << "green存在" << endl;
    else
        cout << "green不存在" << endl;
}

3.multimap的介绍

1. Multimaps是关联式容器,它按照特定的顺序,存储由key和value映射成的键值对,其中多个键值对之间的key是可以重复的。

2. 在multimap中,通常按照key排序和唯一的标识元素,而映射的value存储与key关联的内容。key和value的类型可能不同,通过multimap内部的成员类型value_type组合在一起, value_type是组合key和value的键值对:

typedef pair<const Key, T> value_type;

3. 在内部,multimap中的元素总是通过其内部比较对象,按照指定的特定严格弱排序标准对key进行排序的。

4. multimap通过key访问单个元素的速度通常比unordered_multimap容器慢,但是使用迭代器直接遍历multimap中的元素可以得到关于key有序的序列。

5. multimap在底层用二叉搜索树(红黑树)来实现。

注意:multimap和map的唯一不同就是:map中的key是唯一的,而multimap中key是可以重复

4.multimap的使用

multimap中的接口可以参考map,功能都是类似的。

注意:

1. multimap中的key是可以重复的。

2. multimap中的元素默认将key按照小于来比较

(由于multimap容器允许键值冗余,调用[ ]运算符重载函数时,应该返回键值为key的哪一个元素的value的引用存在歧义,因此在multimap容器当中没有实现[ ]运算符重载函数。)

3. multimap中没有重载operator[]操作

4. 使用时与map包含的头文件相同

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解决恶意IP地址攻击:保卫网络安全的有效方法

随着互联网的发展&#xff0c;网络安全威胁变得日益复杂&#xff0c;其中包括恶意IP地址攻击。这些攻击通常是网络犯罪分子的手段之一&#xff0c;用于入侵系统、窃取数据或进行其他恶意活动。本文将探讨如何解决恶意IP地址攻击&#xff0c;以保护网络安全。 恶意IP地址攻击是…

气膜建筑的维护有哪些?

合理的使用和维护对保证气膜建筑的使用实名具有重要意义&#xff0c;气膜建筑的膜结构主体&#xff0c;索和索网、基础锚固、门禁系统、送风和自动控制系统以及其他所有的附加设备都必须保持良好的运行状态&#xff0c;这就需要操作和维护人员严格按照生产商提供的使用与维护手…

首次启动现存的QT项目

Build的时候&#xff0c;一定要先设置qmake&#xff0c;再设置make。Build的目录应该设置在整个文件的外面&#xff0c;与项目文件平行&#xff0c;互不干扰。 1、Build的构建目录与源代码目录在同一级&#xff1b; 2、选定Build的构建目录后&#xff0c;Excutable的目录自动分…

400G QSFP-DD SR8光模块应用场景解析

在9月份第24届CIOE展会中&#xff0c;我们可以看到大多数企业已全面推出400G系列光模块。本期文章小易将为大家全面分析易天光通信的400G QSFP-DD SR8光模块。作为一种高速率的光模块&#xff0c;400G QSFP-DD SR8光模块广泛应用于数据中心、云计算、企业级网络等领域&#xff…

【Linux】虚拟机安装Linux、客户端工具及Linux常用命令(详细教程)

目录 一、导言 1、引言 2、使用场景 二、Linux安装 1、安装 2、网络配置 2.1、查看网络配置 2.2、更改网络配置 三、安装客户端工具 1、介绍 2、安装MobaXterm 3、换源 4、拍照功能 四、常用命令 一、导言 1、引言 Linux是一个开源的操作系统内核&#xff0c;它最…

Linux C语言进阶

一、二维数组的定义和存储 一、二维数组的定义 1、二维数组的应用&#xff1a;图、方阵 2、数组元素的存放顺序&#xff1a;内存是一维的&#xff0c;二维数组&#xff1a;按行优先 a[1]:表示第一行&#xff0c;也表示a[1][]的所有元素 二、二维数组的初始化、遍历 1、元素的…

Docker swarm集群之compose启动多服务

Docker swarm集群之compose启动多服务 本篇文章是在搭建过Swarm集群基础上进行的&#xff0c;如未搭建过请移步 &#xff1a; [Docker swarm 集群搭建 - Wanwan’s Blog (wanwancloud.cn)] 环境信息 主机名IP主机配置master10.10.10.32c2gnode0110.10.10.42c2gnode0210.10.…

基于mysql的请假系统,java/springboot/jsp/javaweb/tomcat

系统分为 学生/辅导员/超级管理员 登录注册、修改头像、个人资料。 学生登录可以提交请假申请。 辅导员登录可以管理学生信息、管理班级信息、管理课程信息。 超级管理员登陆可以管理用户信息、管理学生信息、管理辅导员信息、管理班级信息、管理二级学院信息、管理课程信息、…

【python图像处理】模糊图像

模糊前 模糊后 模糊 import os from PIL import Image, ImageFilterfacesPath face # 图片文件夹路径 faces os.listdir(facesPath) for face in faces:facePath os.path.join(facesPath, face)image Image.open(facePath)blurred_image image.filter(ImageFilter.BLU…

【ARMv8 SIMD和浮点指令编程】NEON 存储指令——如何将数据从寄存器存储到内存?

和加载指令一样,NEON 有一系列的存储指令。比如 ST1、ST2、ST3、ST4。 1 ST1 (multiple structures) 从一个、两个、三个或四个寄存器存储多个单元素结构。该指令将元素从一个、两个、三个或四个 SIMD&FP 寄存器存储到内存,无需交错。每个寄存器的每个元素都被存储。 …

由于找不到emp.dll无法继续执行此代码问题的五个解决方法

在玩游戏的过程中&#xff0c;我们常常会遇到一些错误提示&#xff0c;其中最常见的就是“找不到emp.dll”&#xff0c;这个问题我们的游戏无法启动运行。本文将分享我在解决这一问题过程中的方法&#xff0c;希望能对遇到类似问题的玩家有所帮助。 emp.dll是一个动态链接库文件…

1820_ChibiOS中的同步消息

全部学习汇总&#xff1a; GreyZhang/g_ChibiOS: I found a new RTOS called ChibiOS and it seems interesting! (github.com) 1. 看到这里提到的这个模型&#xff0c;我在想是不是我一直没有搞定的多核可以利用这个机制来解决。如果是多核&#xff0c;ChibiOS的这种机制是否依…

vue3从基础到入门(一)

文章目录 简介提升使用创建脚手架vite 常用Composition APIsetuprefreactive函数响应式vue2响应式vue3实现响应式 reactive对比ref注意计算属性computed函数 监视watch函数watchEffect函数 生命周期hook函数toRef 简介 2020年9月18日&#xff0c;Vue.js发布3.0版本&#xff0c…

JDK API Diff Report Generator-Java版本对比工具

今天查资料找到了除了EMT4J之外&#xff0c;其他可以用于Java版本迁移的工具。 这里简单的记录一下。 非Java er&#xff0c;有不同意见欢迎评论区交流。 JDK API Diff Report Generator JDK API Diff是一个用于比较不同Java版本API区别的工具。github地址在这里。 例如&am…

10.28总结

目录 一.发布作业 二.写作业 三.批改作业 一.发布作业 点击简答题时———listvie<String>题目列表会新增一个题目 保存该题时———— 获取TextArea的文本,为list当前选中的对象赋值 发布日期不能为过往日期&#xff0c;截止日期不能晚于发布日期。——为发布日期设置…

测试用例基础知识

目录 什么是测试用例&#xff1f; 测试用例格式 测试用例编写 测试用例的设计方法 等价类 边界值 判定表 因果图 流程图 场景法 错误推测法 什么是测试用例&#xff1f; 测试用例 (Test Case)是指对一项特定的软件产品进行测试任务的描述&#xff0c;体现测试方案、…

maven环境变量,安装源,本地仓库配置

1. maven环境变量 我这里用的是idea自带的maven 数值为&#xff1a; D:\software\computer_software\java\IDEAJ\IDEAJ2021.2.1\IntelliJ IDEA 2021.2.1\plugins\maven\lib\maven3\bin 2. 安装源更换为阿里云&#xff08;我不知道清华源是什么网址&#xff0c;网上也没查到&am…

人工智能基础_机器学习007_高斯分布_概率计算_最小二乘法推导_得出损失函数---人工智能工作笔记0047

这个不分也是挺难的,但是之前有详细的,解释了,之前的文章中有, 那么这里会简单提一下,然后,继续向下学习 首先我们要知道高斯分布,也就是,正太分布, 这个可以预测x在多少的时候,概率最大 要知道在概率分布这个,高斯分布公式中,u代表平均值,然后西格玛代表标准差,知道了 这两个…

redux connect组件在手工传入参数时报错

redux使用connect创建一个高阶组件时后&#xff0c;如果手工给该组件传入参数时会因参数不同会报错&#xff0c;此时可以如下处理&#xff1a;