【C++】map和set的使用

目录

一. 关联式容器

二.键值对

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

四.map和set在OJ中的使用


一. 关联式容器

序列式容器:已经接触过STL中的部分容器,比如: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){}
};


 

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

根据应用场景的不同,STL总共实现了两种不同结构的关联式容器:树型结构与哈希结构

树型结构的关联式容器主要有四种:set、multiset、map、multimap

这四种容器的共同点是:使用平衡搜索树(即红黑树)作为其底层,容器中的元素是一个有序的序列。下面一依次介绍这四个容器~
 

1.set

1. set是按照一定次序存储元素的容器
2. 在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的
set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们
3. 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行排序
4. set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对
子集进行直接迭代
5. set在底层是用二叉搜索树(红黑树)实现的

set的模板参数列表

T: set中存放元素的类型,实际在底层存储<value, value>的键值对
Compare: 仿函数,set中元素默认按照小于来比较
Alloc: set中元素空间的管理方式,使用STL提供的空间配置器管理

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的拷贝构造

默认构造、迭代器区间构造、拷贝构造(深拷贝):

int main()
{set<int> s;//默认构造int arr[] = { 1,2,3,4,5 };set<int> s1(arr, arr + 5);//区间构造set<int> s2(s1);//拷贝构造for (auto e : s1) cout << e << " "; cout << endl;for (auto e : s2) cout << e << " "; cout << endl;
}

set的迭代器

函数声明                                      功能介绍

iterator begin()                             返回set中起始位置元素的迭代器

iterator end()                                返回set中最后一个元素后面的迭代器

const_iterator cbegin()                返回set中起始位置元素的const迭代器

const_iterator cend() const          返回set中最后一个元素后面的const迭代器

测试代码:

int main()
{set<int> s;s.insert(1);s.insert(2);s.insert(3);s.insert(4);s.insert(5);s.insert(1);s.insert(2);//排序 + 去重auto it = s.begin();while (it != s.end()){cout << *it << " ";++it;}cout << endl;}

默认是升序排的,如果是想要降序的话:使用仿函数  : less/greater

set的修改操作

下面写一点代码感受一下:

2.multiset

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

1. multiset是按照特定顺序存储元素的容器,其中元素是可以重复的
2. 在multiset中,元素的value也会识别它(因为multiset中本身存储的就是<value, value>组成
的键值对,因此value本身就是key,key就是value,类型为T),multiset元素的值不能在容器
中进行修改(因为元素总是const的),但可以从容器中插入或删除
3. 在内部,multiset中的元素总是按照其内部比较规则(类型比较)所指示的特定严格弱排序准则进行排序
4. multiset容器通过key访问单个元素的速度通常比unordered_multiset容器慢,但当使用迭
代器遍历时会得到一个有序序列
5. multiset底层结构为二叉搜索树(红黑树)

这里只简单演示set与multiset的不同,其他接口与set相同:

另外,如果有多个值相同,find返回的值是中序的第一个:

3.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通常被实现为二叉搜索树,更准确的说:平衡二叉搜索树(红黑树)

pair主要的作用是将两个数据组合成一个数据,两个数据可以是同一类型或者不同类型

map的模板参数

key: 键值对中key的类型

T:键值对中value的类型

Compare: 比较器的类型,map中的元素是按照key来比较的,默认按照小于来比较

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

map的构造

int main()
{map<int, int> m;int arr[] = { 1,1,1,2,3,4,5,6 };for (auto& e : arr){m.insert(make_pair(e, e));}map<int, int>  m1(m.begin(), m.end());//迭代器区间构造for (auto& e : m1)cout << e.first << ":" << e.second << " "; cout << endl;map<int, int>   m2(m1);//拷贝构造for (auto& e : m2)cout << e.first << ":" << e.second << " "; cout << endl;
}

map的修改

int main()
{map<string, string> dict;//匿名对象写法dict.insert(pair<string, string>("排序", "sort"));//使用make_pairdict.insert(make_pair("左边", "left"));//make_pair:函数模板,不需要像pair一样显示声明 //类型,而是通过传参自动推导//使用 { }dict.insert({ "右边", "right" });auto it = dict.begin();while (it != dict.end()){//(*it).firstcout << it->first << ":" << it->second << endl;++it;}cout << endl;for (auto& e : dict){cout << e.first << ":" << e.second << endl;}
}

下面用map实现一下   统计次数

第一种:迭代器

int main()
{//统计水果出现的次数string arr[] = { "苹果", "西瓜", "香蕉", "草莓", "苹果", "西瓜", "苹果" };map<string, int> countMap;for (auto& e : arr){auto it = countMap.find(e);if (it == countMap.end()){countMap.insert(make_pair(e, 1));//不存在就插入,记为1}else{it->second++;//存在就令次数++}}for (auto& kv : countMap){cout << kv.first << ":" << kv.second << endl;}
}

第二种:map[]的使用

int main()
{   //统计水果出现的次数string arr[] = { "苹果", "西瓜", "香蕉", "草莓", "苹果", "西瓜", "苹果" };map<string, int> countMap;for (auto& e : arr){countMap[e]++;}for (auto& kv : countMap){cout << kv.first << ":" << kv.second << endl;}
}

[ ]有三个功能 : 1.插入 2.修改 3.查找

注意:使用[ ] 时要小心,如果查找不在的话它会自己插入

4.multimap

multimap和map的唯一不同就是:map中的key是唯一的,而multimap中key是可以重复的
所以在 multimap里并没有[ ]

1. Multimaps是关联式容器,它按照特定的顺序,存储由key和value映射成的键值对<key,
value>,其中多个键值对之间的key是可以重复的。
2. 在multimap中,通常按照key排序和惟一地标识元素,而映射的value存储与key关联的内
容。key和value的类型可能不同,通过multimap内部的成员类型value_type组合在一起,
value_type是组合key和value的键值对
3. 在内部,multimap中的元素总是通过其内部比较对象,按照指定的特定严格弱排序标准对
key进行排序的
4. multimap通过key访问单个元素的速度通常比unordered_multimap容器慢,但是使用迭代
器直接遍历multimap中的元素可以得到关于key有序的序列
5. multimap在底层用二叉搜索树(红黑树)来实现

测试代码如下:

int main()
{multimap<string, string> dict;dict.insert(make_pair("left", "左边"));dict.insert(make_pair("left", "左边"));dict.insert(make_pair("right", "右边"));dict.insert(make_pair("sort", "排序"));dict.insert(make_pair("left", "离开"));map<string, int> countMap;for (auto& kv : dict){cout << kv.first << ":" << kv.second << endl;}cout << endl;
}

同样的,multimap也是可以统计次数的

int main()
{string arr[] = { "苹果", "西瓜", "香蕉", "草莓", "苹果", "西瓜", "苹果" };multimap<string, int> countMap;for (auto& e : arr){auto it = countMap.find(e);if (it == countMap.end()){countMap.insert(make_pair(e, 1));}else{it->second++;}}for (auto& kv : countMap){cout << kv.first << ":" << kv.second << endl;}
}

下面我们就通过做两个题目来感受一下set和map在OJ中的使用吧~

四.map和set在OJ中的使用

1.两个数组的交集

. - 力扣(LeetCode)

思路:利用set 排序+去重

          将2个数组放入set,然后用双指针进行比较:小的++,相等就同时++,直到其中一个            走完就结束了

class Solution 
{
public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {vector<int> ret;//最终返回的数组//排序+去重set<int> s1(nums1.begin(),nums1.end());set<int> s2(nums2.begin(),nums2.end());//双指针auto it1 = s1.begin();auto it2 = s2.begin();while(it1!=s1.end() && it2!=s2.end())//有一个结束就结束了{if(*it1 == *it2){ret.push_back(*it1);it1++;it2++;}else if(*it1>*it2){it2++;}else{it1++;}}return ret;}
};

2.前K个高频单词

. - 力扣(LeetCode)

这里要注意的是:

1.map的迭代器不是随机迭代器而是双向迭代器,所以如果要用sort排序是不能用map的,我们可以考虑用vector将map已经从单词表读入的数据拷过来~

2.我们这里排序的依据是单词出现的次数,如果我们直接排序,默认pair<string,int>是按照单词的各个字母的ASCII值来排的,显然不是我们想要的效果,以及我们要按单词频率从高到低实现一个降序,所以我们可以考虑写一个仿函数

class Solution 
{
public:struct Compare{bool operator()(pair<string,int>& x,pair<string,int>& y){//第二个条件很重要,不加就无法满足不同的单词有相同出现频率按字典顺序这个条件,除非将下面的sort换成stable_sortreturn x.second > y.second || (x.second == y.second && (x.first < y.first));}};vector<string> topKFrequent(vector<string>& words, int k) {map<string,int> countMap;for (auto& e: words)countMap[e]++;//map从单词表words读入数据vector<pair<string,int>> v(countMap.begin(),countMap.end());sort(v.begin(),v.end(),Compare());//按照单词出现频率降序排序vector<string> strV;//最终结果返回的数组for (int i = 0;i<k;i++)//前 k 个出现次数最多的单词{strV.push_back(v[i].first);//将单词放入}return  strV;}
};

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

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

相关文章

Axure RP移动端医院在线挂号app问诊原型图模板

医疗在线挂号问诊Axure RP原型图医院APP原形模板&#xff0c;是一款原创的医疗类APP&#xff0c;设计尺寸采用iPhone13&#xff08;375*812px&#xff09;&#xff0c;原型图上加入了仿真手机壳&#xff0c;使得预览效果更加逼真。 本套原型图主要功能有医疗常识科普、医院挂号…

一、单例模式

文章目录 1 基本介绍2 实现方式2.1 饿汉式2.1.1 代码2.1.2 特性 2.2 懒汉式 ( 线程不安全 )2.2.1 代码2.2.2 特性 2.3 懒汉式 ( 线程安全 )2.3.1 代码2.3.2 特性 2.4 双重检查2.4.1 代码2.4.2 特性 2.5 静态内部类2.5.1 代码2.5.2 特性 2.6 枚举2.6.1 代码2.6.2 特性 3 实现的要…

Typora 1.5.8 版本安装下载教程 (轻量级 Markdown 编辑器),图文步骤详解,免费领取

文章目录 软件介绍软件下载安装步骤激活步骤 软件介绍 Typora是一款基于Markdown语法的轻量级文本编辑器&#xff0c;它的主要目标是为用户提供一个简洁、高效的写作环境。以下是Typora的一些主要特点和功能&#xff1a; 实时预览&#xff1a;Typora支持实时预览功能&#xff0…

UI设计中的响应式布局策略:让您的界面在各种设备上都表现出色

UI界面设计它是人与机器之间交互的媒介&#xff0c;也是客户体验的媒介&#xff08;UX&#xff09;一个组成部分。操作界面由两个主要部分组成&#xff1a;视觉设计&#xff08;即传达产品的外观和感觉&#xff09;和交互设计&#xff08;即元素功能和逻辑组织&#xff09;。用…

Python创建Excel表和读取Excel表的基础操作

下载openpyxl第三方库 winr打开命令行输入cmd 这个如果不行可以试试其他方法&#xff0c;在运行Python代码的软件里也有直接下载的地方&#xff0c;可以上网搜索 创建Excel表 示例代码&#xff1a;最后要记得保存&#xff0c;可以加一句提示语句。 import openpyxl lst[100,…

TCP/IP四层模型、OSI七层模型

OSI定义了网络互连的七层框架&#xff08;物理层、数据链路层、网络层、传输层、会话层、表示层、应用层&#xff09;TCP/IP 四层模型是目前被广泛采用的一种模型&#xff0c;由以下 4 层组成&#xff1a;应用层、传输层、网络层、网络接口层 FTP&#xff08;File Transfer Pro…

puzzle(0611)《组合+图论》追捕问题

目录 一&#xff0c;追及问题 1&#xff0c;警察和小偷 2&#xff0c;旋转的4个硬币 3&#xff0c;抓狐狸 二&#xff0c;围堵问题 三&#xff0c;追及围堵 一&#xff0c;追及问题 1&#xff0c;警察和小偷 如下图&#xff0c;警察先走&#xff0c;警察和小偷轮流一人…

Linux入门笔记(指令)

操作系统是什么&#xff1f; 操作系统是一款做软硬件管理的软件。计算机系统自下而上可以大致分为4部分&#xff1a;硬件、操作系统、应用程序和用户。操作系统管理各种计算机硬件&#xff0c;为应用程序提供基础&#xff0c;并且充当计算机硬件与用户之间的中介。重点&#x…

vue v-for展示元素分两栏 中间使用分割线

1.效果展示: 2.代码展示: <template><div class"container"><div class"column" v-for"(item, index) in items" :key"index"><div class"item">{{ item }}</div><div v-if"index %…

阿里云ACP云计算高级攻城狮通用知识

&#x1f525;概述 阿里云云计算高级工程师ACP认证是面向使用阿里云云计算产品的架构、开发、运维类人员的专业技术认证&#xff0c;主要考核考生利用阿里云云计算技术服务体系设计稳定、安全、高性能、易扩展、低成本的企业云计算架构的能力。 前提&#xff1a;在写适用人群…

云计算实训室的核心功能有哪些?

在当今数字化转型浪潮中&#xff0c;云计算技术作为推动行业变革的关键力量&#xff0c;其重要性不言而喻。唯众&#xff0c;作为教育实训解决方案的领先者&#xff0c;深刻洞察到市场对云计算技能人才的迫切需求&#xff0c;精心打造了云计算实训室。这一实训平台不仅集成了先…

使用Python实现高效的图像处理:基于OpenCV的实战指南

目录 引言 准备工作 安装Python与OpenCV 导入必要的库 基本图像处理操作 读取与显示图像 转换图像颜色空间 图像变换 图像滤波 实战案例&#xff1a;边缘检测 引言 在现代科技快速发展的今天&#xff0c;图像处理已成为众多领域不可或缺的一部分&#xff0c;包括计算…

Haproy服务

目录 一.haproxy介绍 1.主要特点和功能 2.haproxy 调度算法 3.haproxy 与nginx 和lvs的区别 二.安装 haproxy 服务 1. yum安装 2.第三方rpm 安装 3.编译安装haproxy 三.配置文件详解 1.官方地址配置文件官方帮助文档 2.HAProxy 的配置文件haproxy.cfg由两大部分组成&…

StarRocks on AWS Graviton3,实现 50% 以上性价比提升

在数据时代&#xff0c;企业拥有前所未有的大量数据资产&#xff0c;但如何从海量数据中发掘价值成为挑战。数据分析凭借强大的分析能力&#xff0c;可从不同维度挖掘数据中蕴含的见解和规律&#xff0c;为企业战略决策提供依据。数据分析在营销、风险管控、产品优化等领域发挥…

网络安全----防御----防火墙双机热备

实验要求&#xff1a; 1&#xff0c;对现有网络进行改造升级&#xff0c;将当个防火墙组网改成双机热备的组网形式&#xff0c;做负载分担模式&#xff0c;游客区和DMZ区走FW4&#xff0c;生产区和办公区的流量走FW1 2&#xff0c;办公区上网用户限制流量不超过100M&#xff0…

【go】Excelize处理excel表 带合并单元格、自动换行与固定列宽的文件导出

文章目录 1 简介2 相关需求与实现2.1 导出带单元格合并的excel文件2.2 导出增加自动换行和固定列宽的excel文件 1 简介 之前整理过使用Excelize导出原始excel文件与增加数据校验的excel导出。【go】Excelize处理excel表 带数据校验的文件导出 本文整理使用Excelize导出带单元…

数据挖掘与分析部分实验与实训项目报告

一、机器学习算法的应用 1. 朴素贝叶斯分类器 相关代码 import pandas as pd from sklearn.model_selection import train_test_split from sklearn.naive_bayes import GaussianNB, MultinomialNB from sklearn.metrics import accuracy_score # 将数据加载到DataFrame中&a…

Notepad++换安装路径之后,右键打开方式报错:Windows无法访问指定设备、路径或文件。你可能没有适当的权限访问该项目。的处理方法

把Notepad添加到右键打开方式&#xff0c;可以参考下面的3篇文章添加&#xff1a; https://blog.csdn.net/xiaoerbuyu1233/article/details/88287747 https://blog.csdn.net/qq_44000337/article/details/120277317 https://www.cnblogs.com/zhrngM/p/12899026.html 这里主要是…

数据结构——位图布隆过滤器

一、位图 1.1 概念 所谓位图&#xff0c;就是用每一位来存放某种状态&#xff0c;适用于海量数据&#xff0c;数据无重复的场景。通常是用来判断某个数据存不存在的。 数据是否在给定的整形数据中&#xff0c;结果是在或者不在&#xff0c;刚好是两种状态&#xff0c;那么可以…

使用LVS+NGinx+Netty实现数据接入

数据接入 链接参考文档 LVSKeepalived项目 车辆数据上收&#xff0c;TBox通过TCP协议连接到TSP平台 建立连接后进行数据上传。也可借由该连接实现远程控制等操作。 通过搭建 LV—NGinx—Netty实现高并发数据接入 LVS&#xff1a;四层负载均衡&#xff08;位于内核层&#x…