C++ map set

一.关联式容器

在初期学过的vector、list、deque、forward_list(C++11)等,底层都为线性序列的序列式容器。

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

二.键值对

键值对是用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量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){}
};

三.set

set介绍

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

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

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

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

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

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

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

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

9.set中查找某个元素,时间复杂度为O(logn)。

10.set中的元素不允许修改。

12.与map/multimap不同,map/multimap中存储的是真正的键值对<key, value>,set中只放value,但在底层实际存放的是由<value, value>构成的键值对,因此在set容器中插入元素时,只需要插入value即可,不需要构造键值对。

set定义

    set<int> s1;//1.空的set容器set<int> s2(s1);//2.用已有的s1拷贝构造s2string str("bear");set<char> s3(str.begin(), str.end());//3.用迭代器区间构造

set使用

插入删除操作

insert(x)当容器中没有等价元素的时候,将元素 x 插入到 set 中
erase(x)删除值为 x 的 所有 元素,返回删除元素的个数
erase(pos)删除迭代器为 pos 的元素,要求迭代器必须合法
erase(first,last)删除迭代器在 [first,last) 范围内的所有元素
clear清空容器
swap交换两个容器的数据

 查找操作

count(x)返回 set 内键为 x 的元素数量
find(x)在 set 内存在键为 x 的元素时会返回该元素的迭代器,否则返回 end()
lower_bound(x)返回指向首个不小于给定键的元素的迭代器。如果不存在这样的元素,返回 end()
upper_bound(x)返回指向首个大于给定键的元素的迭代器。如果不存在这样的元素,返回 end()
empty()返回容器是否为空
size()返回容器内元素个数

 迭代器

begin()/cbegin()返回指向首元素的迭代器,其中 *begin = front
end()/cend()返回指向数组尾端占位符的迭代器,注意是没有元素的
rbegin()/crbegin()返回指向逆向数组的首元素的逆向迭代器,可以理解为正向容器的末元素
rend()/crend()返回指向逆向数组末元素后一位置的迭代器,对应容器首的前一个位置,没有元素

 以上列出的迭代器中,含有字符 c 的为只读迭代器,你不能通过只读迭代器去修改 set 中的元素的值。如果一个 set 本身就是只读的,那么它的一般迭代器和只读迭代器完全等价。只读迭代器自 C++11 开始支持。

 下列对常用的函数进行模拟:

#include<iostream>
#include<set>
using namespace std;int main()
{set<int> s1;//insert函数s1.insert(1);s1.insert(2);s1.insert(3);s1.insert(4);s1.insert(5);s1.insert(6);//遍历一,范围forfor (auto i : s1){cout << i << " ";}cout << endl;//1 2 3 4 5 6//指定元素个数cout << s1.count(1) << endl;//1个//容器大小cout << s1.size() << endl;//6//erase函数1s1.erase(6);//删除元素6//erase函数2set<int>::iterator pos = s1.find(5);if (pos != s1.end()){s1.erase(pos);}//遍历二(正向迭代器)set<int>::iterator it = s1.begin();while (it != s1.end()){cout << *it << " ";it++;}cout << endl;//1 2 3 4//clear函数s1.clear();//容器判空cout << s1.empty() << endl;//1//遍历方式三(反向迭代器)set<int>::reverse_iterator rit = s1.rbegin();while (rit != s1.rend()){cout << *rit << " ";rit++;}cout << endl;//   为空
}

multiset

multiset与set的底层与函数基本相同,不同的是multiset可以允许键值冗余,也就是说multiset容器中的元素是可以重复的

四.map

map介绍

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

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

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

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

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

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

map定义

    map<int, int> m1;//构造一个key和value都为int的空容器map<int, int> m2(m1);//拷贝m1构造一个key和value都为int的空容器map<int, int> m3(m2.begin(), m2.end());//用迭代器构造一个key和value都为int的空容器

map使用

map插入

在map中插入,需要同时插入key和value

再来看看map插入函数的原型

pair<iterator,bool> insert (const value_type& val);

insert函数的参数显示为value_type类型,实际上value_type就是pair类型的别名

typedef pair<const Key, T> value_type;

所以,我们向map容器插入元素时,需要用key和value构造一个pair对象,然后再将pair对象作为参数传入insert函数。

调用make_pair函数模板插入

库中会提供make_pair模板:

template <class T1, class T2>
pair<T1, T2> make_pair(T1 x, T2 y)
{return (pair<T1, T2>(x, y));
}

我们只需要向make_pair函数传入key和value,该函数模板会根据传入参数类型进行自动隐式推导,最终构造并返回一个对应的pair对象。

#include<iostream>
#include<map>
using namespace std;int main()
{//map插入map<int, string> m1;m1.insert(make_pair(1, "one"));m1.insert(make_pair(2, "two"));m1.insert(make_pair(3, "three"));for (auto i : m1){cout << "<" << i.first << "," << i.second << ">";cout << endl;}cout << endl;//<1,one> <2,two> <3,three>return 0;
}

在前面我们可以看到,insert函数是有返回值的,该返回值也是一个pair对象,该pair对象第一个成员的类型是map的迭代器类型,第二个成员的类型是一个bool类型,下面介绍具体含义:

1.若带插入元素的键值key在map当中不存在,则insert函数插入成功,并返回插入后元素的迭代器和true。

2.若待插入元素的键值key在map当中已经存在,则insert函数插入失败,并返回map当中键值为key的元素迭代器和false。

map查找

map查找函数的原型为:

iterator find(const key_type& k);

该函数含义为,根据所给的key值在map中进行查找,假如找到了,那么返回对应元素的迭代器;如果没找到,那么返回最后一个元素下一个位置的正向迭代器。

#include<iostream>
#include<map>
using namespace std;int main()
{map<int, string> m1;m1.insert(make_pair(1, "one"));m1.insert(make_pair(2, "two"));m1.insert(make_pair(3, "three"));//map查找map<int, string>::iterator pos = m1.find(3);if (pos != m1.end()){cout << pos->second << endl;//three}return 0;
}

map删除

先来看看map删除函数的原型:

size_type erase(const key_type& k);void erase(ietrator posision);

根据函数原型可以看到,可以根据key删除指定元素,也可以根据迭代器删除指定元素。要是根据key删除,那么返回删除元素的个数。

#include<iostream>
#include<map>
using namespace std;int main()
{map<int, string> m1;m1.insert(make_pair(1, "one"));m1.insert(make_pair(2, "two"));m1.insert(make_pair(3, "three"));//map删除cout << m1.erase(3);//1map<int, string>::iterator pos = m1.find(1);if (pos != m1.end()){m1.erase(pos);}return 0;
}

map的[]运算符重载

map的[]运算符重载函数原型为:

mapped_type& operator[] (const key_type& k);

可以看到,[]运算符重载函数的参数是一个key值,而这个函数的返回值如下:

(*((this->insert(make_pair(k, mapped_type()))).first)).second

 我们将它进行拆解分析:

1.调用insert函数插入键值对。

2.拿出从insert函数获取到的迭代器。

3.返回该迭代器位置元素的值value。

下面来看看拆解代码:

mapped_type& operator[] (const key_type& k)
{//1、调用insert函数插入键值对pair<iterator, bool> ret = insert(make_pair(k, mapped_type()));//2、拿出从insert函数获取到的迭代器iterator it = ret.first;//3、返回该迭代器位置元素的值valuereturn it->second;
}

再来看看具体使用场景:

#include <iostream>
#include <string>
#include <map>
using namespace std;int main()
{map<int, string> m1;m1.insert(make_pair(1, "one"));m1.insert(make_pair(2, "two"));m1.insert(make_pair(3, "three"));m[2] = "bear"; //修改key值为2的元素的value为bearm[4] = "four"; //插入键值对<4, "four">for (auto e : m){cout << "<" << e.first << "," << e.second << ">" << " ";}cout << endl; //<1,one> <2,bear> <3,three> <4,four>return 0;
}

总结:

1.如果k不在map中,那么先插入键值对<k,V()>,然后返回该键值对中对V对象的引用。

2.如果k在map中,则返回键值为k的元素对应V对象的引用。

map迭代器

begin获取容器中第一个元素的正向迭代器
end获取容器中最后一个元素下一个位置的正向迭代器
rbegin获取容器中最后一个元素的反向迭代器
rend获取容器中第一个元素前一个位置的反向迭代器

使用方法和set的相同。

map的其它成员函数

size获取容器中元素的个数
empty判断容器是否为空
clear清空容器
swap交换两个容器中的数据
count获取容器中指定key值的元素个数

multimap

multimap与map和multiset与set的关系几乎相同,multimap也允许键值冗余

在find函数中:

map对象的find功能为:返回值为键值为key的元素的迭代器。

multimap对象的find功能为:返回底层搜索树中序的第一个键值为key的元素的迭代器。

在count函数中:

map对象的count功能为:键值为key的元素存在则返回1,不存在则返回0(find成员函数可代替)

multimap对象的count功能为:返回键值为key的元素个数(find成员函数不可代替)。

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

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

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

相关文章

qiankun实现微前端,vue3为主应用,分别引入vue2和vue3微应用

1、vue3主应用配置 1、安装 qiankun yarn add qiankun # 或者 npm i qiankun -S2、在主应用中注册微应用 import { registerMicroApps, start } from "qiankun" const apps [{ name: vue2App, // 应用名称 xs_yiqing_vue2entry: //localhost:8080, // vue 应用…

apk一键换包名工具

工作需要 手动撸了个一键换包名的工具 1 给AndroidManifest.xml修改包名(修改完成后会覆盖原来的文件) java -jar xmleditor-1.0.jar -pkg [AndroidMainifest.xml] 2 给apk修改包名(修改完成后会在当前目录下生成一个新的apk) java -jar xmleditor-1.0.jar -pkgapk [xxx.ap…

C语言(递归)

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸各位能阅读我的文章&#xff0c;诚请评论指点&#xff0c;关注收藏&#xff0c;欢迎欢迎~~ &#x1f4a5;个人主页&#xff1a;小羊在奋斗 &#x1f4a5;所属专栏&#xff1a;C语言 本系列文章为个人学习笔记&#x…

数据结构——实现通讯录(附源码)

乐观学习&#xff0c;乐观生活&#xff0c;才能不断前进啊&#xff01;&#xff01;&#xff01; 我的主页&#xff1a;optimistic_chen 我的专栏&#xff1a;c语言 点击主页&#xff1a;optimistic_chen和专栏&#xff1a;c语言&#xff0c; 创作不易&#xff0c;大佬们点赞鼓…

layui的treeTable组件,多层级上传按钮失效的问题解决

现象描述: layui的treeTable 的上传按钮在一层能用&#xff0c;展开后其他按钮正常点击&#xff0c;上传按钮无效。 具体原因没有深究&#xff0c;大概率是展开的子菜单没有被渲染treeTable的done管理到&#xff0c;导致没有重绘上传按钮。 解决方案: 不使用layu的上传组件方法…

C语言常见的动态内存错误及几个经典笔试题以及c/c++内存开辟空间等的介绍

文章目录 前言一、常见的动态内存错误1. 对NULL指针的解引用操作2. 对动态开辟空间的越界访问3. 对非动态开辟内存使用free()4. 使用free释放一块动态开辟内存的一部分5. 对同一块动态内存多次释放6. 动态开辟内存忘记释放&#xff08;内存泄漏&#xff09; 二、几个经典笔试题…

rust容器、迭代器

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff1a;点击跳转 目录 一&#xff0c;std容器 1&#xff0c;Vec&#xff08;向量、栈&#xff09; 2&#xff0c;VecDeque&#xff08;队列、双端队…

邦注科技 模具保护器 CCD电子眼 专业工业视觉检测设备

模具保护器是一种用于保护模具的设备&#xff0c;可以在塑料压铸和冲床等加工过程中起到保护模具的作用。以下是关于模具保护器在保护塑料压铸和冲床模具方面的应用&#xff1a; 塑料压铸模具保护器&#xff1a; 防止碰撞&#xff1a;在塑料压铸过程中&#xff0c;模具可能会…

Vue 3中,`toRef` 和 `toRefs`

在Vue 3中&#xff0c;toRef 和 toRefs 是两个帮助函数&#xff0c;它们用于从 reactive 对象中提取出响应式的引用。这两个函数在处理复杂的响应式状态或者在组合式API中非常有用。 ### toRef toRef 创建一个 ref 对象&#xff0c;它是一个对于 reactive 对象中某个属性的响…

MindSponge分子动力学模拟——安装与使用

技术背景 昇思MindSpore是由华为主导的一个&#xff0c;面向全场景构建最佳昇腾匹配、支持多处理器架构的开放AI框架。MindSpore不仅仅是软件层面的工具&#xff0c;更重要的是可以协同华为自研的昇腾Ascend平台&#xff0c;做到软硬件一体的行业解决方案。基于MindSpore的高通…

解析源代码安全的防泄密解决途径

随着各行各业业务数据信息化发展&#xff0c;各类产品研发及设计等行业&#xff0c;都有关乎自身发展的核心数据&#xff0c;包括业务数据、代码数据、机密文档、用户数据等敏感信息&#xff0c;这些信息数据有以下共性&#xff1a; 属于核心机密资料&#xff0c;万一泄密会对…

YOLOv9全网最新改进系列:YOLOv9完美融合标准化的注意力模块NAM,高效且轻量级的归一化注意力机制,助力目标检测再上新台阶!

YOLOv9全网最新改进系列&#xff1a;YOLOv9完美融合标准化的注意力模块NAM&#xff0c;高效且轻量级的归一化注意力机制&#xff0c;助力目标检测再上新台阶&#xff01;&#xff01;&#xff01; YOLOv9原文链接戳这里&#xff0c;原文全文翻译请关注B站Ai学术叫叫首er B站全…

STM32自学教程-前言

目录 为什么要写这个教程 学习STM32需要具备的知识 为什么要写这个教程 其实最重要的目的是为了总结自己学习和整理的资料&#xff0c;同时锻炼下自己的写作水平。毕业已经十多年了&#xff0c;平常也一直爱学习一些自己感兴趣的东西。自己对软件硬件都非常感…

GEE-python 更新提示(含网页上Colab / JupyterLab 和基于本地的操作 )

今天收到了来在GEE开发中心的邮件,作为 Google 对安全性改进的一部分,您将看到(Python)ee.Authenticate()和(命令行)earthengine 身份验证调用的行为方式发生了一些变化。他们将继续生成凭证文件,但审批步骤会有所不同。 具体修改部分: 这仅适用于使用 Python 库或命…

[笔试训练](十六)

目录 046:字符串替换 047:神奇数 048:DNA序列 046:字符串替换 字符串替换_牛客题霸_牛客网 (nowcoder.com) 题目&#xff1a; 题解&#xff1a; 简单模拟题~ class StringFormat { public:string formatString(string str, int n, vector<char> arg, int m) {strin…

Springboot-Jedis实现分布式锁

依赖 <dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.3.0</version></dependency>配置类 Configuration EnableConfigurationProperties(RedisProperties.class) public class Redi…

QT4-升级到QT5(1)

1.C报错汇总_nafxcwd.lib error lnk2001-CSDN博客1 1.QT3Support QWidget::setShown 改为QWidget::setVisible 2.头文件 #include<QWidget> 3.部分函数替换

了解WebSocket

1.概念&#xff1a; WebSocket是一种在单个TCP连接上进行全双工通信的协议&#xff0c;属于应用层协议。 WebSocket使得客户端和服务器之间的数据交换变得更加简单&#xff0c;允许服务端主动向客户端推送数据。在WebSocket API中&#xff0c;浏览器和服务器只需要完成一次握…

电脑怎么压缩视频?win端、Mac端压缩工具分享~

我们经常需要处理和分享视频文件。然而&#xff0c;视频文件往往会占用大量的存储空间&#xff0c;特别是高分辨率和高质量的视频。为了方便存储和分享&#xff0c;我们常常需要将视频文件进行压缩。本文将介绍如何使用电脑系统win端或Mac端自带的视频编辑器、以及常用的剪辑软…

使用docker-compose编排lnmp(dockerfile)完成wordpress

文章目录 使用docker-compose编排lnmp&#xff08;dockerfile&#xff09;完成wordpress1、服务器环境2、Docker、Docker-Compose环境安装2.1 安装Docker环境2.2 安装Docker-Compose 3、nginx3.1 新建目录&#xff0c;上传安装包3.2 编辑Dockerfile脚本3.3 准备nginx.conf配置文…