C++——map和set的基本使用

目录

一,关联式容器

二,键值对

三,set的使用

3.1 set介绍

3.2 set的插入和删除

3.3 set的pair

3.4 multiset

四,map的使用

4.1 map介绍

4.2 map实现简易字典

 4.3 map实现统计次数

4.4 map的[]

五,使用map或set解决部分OJ题

5.1 复杂链表的复制

5.2 前K个高频单词

5.2.1 解法一:使用sort算法排序

5.2.2 使用multimap解决

 5.2.3 使用set的特性加仿函数解决

 5.3 两个数组的交集


一,关联式容器

在前面的文章里,我们以及接触过STL的部分容器,包括:vector,list,deque等,这些容器同称为序列式容器,因为其底层为线性序列的数据结构,里面存的是元素本身。

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

二,键值对

键值对是用来表示居于一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value。key代表监事,value表示与key对应的信息。比如建一个英汉互译的字典,所以这个字典中,英语单词与其含义是一一对应的关系,即通过该单词可以在字典中找到对应的中文含义

下面是STL中关于键值对pair的定义

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的使用

3.1 set介绍

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

②在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的

③在内部,set中的元素总是按照其内部比较对象所指示的特点排序准则进行排序

④set在底层是用红黑树实现的

3.2 set的插入和删除

void test_set1()
{//set<int> s = {1,2,1,6,3,8,5};//列表初始化int a[] = { 1,2,1,6,3,8,5 };set<int> s(a, a + sizeof(a) / sizeof(int));//set支持通过迭代器区间初始化//set<int,greater<int>> s(a, a + sizeof(a) / sizeof(int));可以自行控制这颗树//set间接完成了  排序+去重,因为set底层是一个搜索二叉树set<int>::iterator it = s.begin();while (it != s.end()){//搜索树不允许修改key,可能会破坏搜索的规则//*it += 1;cout << *it << " ";it++;}cout << endl;//删除//方法1s.erase(1);for (auto e : s){cout << e << " ";}cout << endl;//方法2set<int>::iterator pos = s.find(2);if (pos != s.end())//判断有没有找到{s.erase(pos);}for (auto e : s){cout << e << " ";}cout << endl;//count()返回数据个数,但由于set默认去重只能返回0或1,所以一般用作判断该数是否存在cout << s.count(3) << endl;  //判断在不在,并且返回个数cout << s.count(30) << endl;
}

 

void test_set2()
{set<int> myset;set<int>::iterator itlow, itup;for (int i = 0; i < 10; i++)myset.insert(i * 10);  //10 20 30 40 50 60 70 80 90itlow = myset.lower_bound(25);//返回的是>=val的第一个值,此处返回30itup = myset.upper_bound(60);//返回的是>val的第一个值,此处返回70cout << "[" << *itlow << "," << *itup << "]" << endl;myset.erase(itlow, itup);//删除这两个值所代表的范围之间的数
}

 

3.3 set的pair

void test_set3()//pair用来记录一对数据
{set<int> myset;for (int i = 1; i <= 5; i++)myset.insert(i * 10);//10 20 30 40 50 pair<set<int>::const_iterator, set<int>::const_iterator> ret;ret = myset.equal_range(40);cout << "the lower bound points to : " << *ret.first << endl;cout << "the upper bound points to : " << *ret.second << endl;
}

 

3.4 multiset

void test_multiset()//multiset与set不一样的是,multiset允许有重复值
{int a[] = { 3,1,2,1,6,3,8,3,5,3,1 };multiset<int> s(a, a + sizeof(a) / sizeof(int));for (auto e : s){cout << e << " ";}cout << endl;cout << s.count(1) << endl;//这里的count就是记录个数了auto pos = s.find(3);//find时如果有多个值,返回中序的第一个位置,如果想找第二个3,把迭代器++一下就是第二个3while (pos != s.end()){cout << *pos << " ";++pos;}cout << endl;s.erase(3);//如果要删除的值有多个,删除所有的值for (auto e : s){cout << e << " ";}
}

四,map的使用

4.1 map介绍

①map是关联容器,它按照特点的次序(按照key来比较)存储由简直key和value组合而成的元素

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

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

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

4.2 map实现简易字典

void test_map1()
{map<string, string> dict;pair<string, string> kv1("sort","排序");//隐式类型转换dict.insert(kv1);//但是上面有点麻烦,所以这时候“匿名对象”就排上用场了dict.insert(pair<string, string>("test", "测试"));dict.insert(pair<string, string>("string", "字符串"));typedef pair<string, string> DictkV;dict.insert(DictkV("string", "xxx"));//只看king相不相同,所以这里不用xxx替换“字符串”,king已经有了,所以直接插入失败//大家也不喜欢用typedef,喜欢用下面这个东东dict.insert(make_pair("left", "左边"));/*template<class T1,class T2>pair<T1, T2> make_pair(T1 x, T2 y){return (pair<T1, T2>(x, y));}*///map遍历//map<string, string>::iterator it = dict.begin();auto it = dict.begin();while (it != dict.end()){//cout << *it << endl;//报错,pair不支持流插入,迭代器的解引用是去调用operator*,set只有king就返回king的引用,pair有两个值first和secong,一个函数的调用用不允许返回两个值//cout << (*it).first << (*it).second << endl;虽然这样可以排序,但是map不喜欢这样搞cout << it->first << it->second << endl;//这里的it是指针,->经过重载,it->返回pari*,然后再->就可以找到first,但是就变成了it->->太难看了,所以编译器优化掉了一个->++it;}cout << endl;for (auto& kv : dict){cout << kv.first << ":" << kv.second << endl;}
}

 

 4.3 map实现统计次数

void test_map2()
{string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜","苹果", "香蕉", "苹果", "香蕉" };//统计次数//map<string, int> countMap;//for(auto & str : arr)//{//	//map<string, int>::iterator it = countMap.find(str);//	//if (it != countMap.end()) //找到了//	//{//	//	//说明该水果是有的//	//	//(*it).second++;//	//	it->second++;//	//}//	//else //没找到//	//{//	//	//说明是一个新水果,插入一个//	//	countMap.insert(make_pair(str, 1));//	//}//}//上面的是常规的统计次数的方法,但是太麻烦了,我们一般用[]将查找插入修改一并完成map<string, int> countMap;for (auto& str : arr){countMap[str]++; //重载的operator[]//1,str不在countMap中,插入pair(str,int()),然后再返回++                                   key已经在map中,返回pair(key_iterator,false);//2,str在countMap中,直接返回value的引用再++                                              key不在map中,返回pair(new_key_iterator,true);}map<string, int>::iterator it = countMap.begin();while (it != countMap.end()){cout << it->first << ":" << it->second << endl;++it;}/*V& operator[](const K& key){pair<iterator, bool> ret = insert(make_pair(key, V()); //insert完成了查找,bool表示插入是否成功return ret.first->second}*/
}

 

4.4 map的[]

void test_map3()
{map<string, string> dict;dict.insert(make_pair("sort", "排序"));dict.insert(make_pair("string", "字符串"));dict.insert(make_pair("count", "计数"));dict["left"];                   //插入 dict["right"] = "右边";         //插入+修改dict["string"] = "(字符串)";  //修改cout << dict["string"] << endl; //查找,打印 "(字符串)"map<string, string>::iterator it = dict.begin();while (it != dict.end()){cout << it->first << ":" << it->second << endl;++it;}
}

五,使用map或set解决部分OJ题

5.1 复杂链表的复制

题目出处:LCR 154. 复杂链表的复制 - 力扣(LeetCode)

class Solution
{
public:Node* copyRandomList(Node* head){map<Node*,Node*> copyNodeMap;Node* cur = head;Node* copyhead, *copytail;copyhead = copytail = nullptr;while (cur){Node* copy = new Node(cur->val);copyNodeMap[cur] = copy;if (copytail == nullptr){copytail = copyhead = copy;}else{copytail->next = copy;copytail = copytail->next;}cur = cur->next;}cur = head;Node* copy = copyhead;while (cur){if (cur->random == nullptr){copy->random = nullptr;}else{copy->random = copyNodeMap[cur->random];}cur = cur->next;copy = copy->next;}return copyhead;}
};

5.2 前K个高频单词

题目出处:692. 前K个高频单词 - 力扣(LeetCode)

5.2.1 解法一:使用sort算法排序

class Solution {
public://比较大小仿函数struct Compare{bool operator()(const pair<string, int>& kv1, const pair<string, int>& kv2){return kv1.second > kv2.second || kv1.second == kv2.second && kv1.first < kv2.first;}};vector<string> topKFrequent(vector<string>& words, int k) {map<string, int> countMap;for (auto& str : words){countMap[str]++; //统计次数}//因为需要使用sort排序,而map是一个双向迭代器,不是随机迭代器也就是不能通过下标访问元素//所以我们先把值放进vector中排序vector<pair<string, int>> v(countMap.begin(), countMap.end());//stable_sort(v.begin(),v.end(),Compare()); //C++提供的稳定的排序函数sort(v.begin(), v.end(), Compare());vector<string> v1;for (size_t i = 0; i < k; i++){v1.push_back(v[i].first);}return v1;}
};

5.2.2 使用multimap解决

class Solution {
public:/*struct Compare{bool operator()(const int& key1, const int& key2) const{return key1 > key2;}};*/vector<string> topKFrequent(vector<string>& words, int k) {map<string, int> countMap;for (auto& str : words){countMap[str]++; //统计次数}//直接使用multimap进行排序//multimap<int, string, Compare> sortMap;multimap<int, string, greater<int>> sortMap; //巧合,题目给的测试用例插入的顺序刚好符合要求//当次数相同时,红黑树插入时插入在右边,如果插到左边就不行了for (auto& kv : countMap){sortMap.insert(make_pair(kv.second, kv.first));}vector<string> ret;auto it = sortMap.begin();while (k--){ret.push_back(it->second);++it;}return ret;}
};

 5.2.3 使用set的特性加仿函数解决

class Solution3 {
public:struct Compare{bool operator()(const pair<string, int>& kv1, const pair<string, int>& kv2) const{return kv1.second > kv2.second || kv1.second == kv2.second && kv1.first < kv2.first;}};vector<string> topKFrequent(vector<string>& words, int k) {map<string, int> countMap;for (auto& str : words){countMap[str]++; //统计次数}//这里默认是升序,暂时我们要降序,所以加仿函数set<pair<string, int>, Compare> sortSet(countMap.begin(), countMap.end());vector<string> ret;auto it = sortSet.begin();while (k--){ret.push_back(it->first);++it;}return ret;}
};

 5.3 两个数组的交集

题目出处:349. 两个数组的交集 - 力扣(LeetCode)

class Solution {
public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2){//先去重set<int> s1(nums1.begin(), nums1.end());set<int> s2(nums2.begin(), nums2.end());auto it1 = s1.begin();auto it2 = s2.begin();vector<int> ret;//前面完成了去重,不相等也就不是交集,小的值的迭代器++,相等,拿出相等值然后两个迭代器同时++while (it1 != s1.end() && it2 != s2.end()){if (*it1 < *it2){it1++;}else if (*it2 < *it1){it2++;}else{ret.push_back(*it1);it1++;it2++;}}return ret;//如果要找差集,那么相等时同时++,不相等,小的就是差集//如果一个走完了,另一个没有走完,那么没走完的剩下的值也是差集}
};

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

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

相关文章

LV.13 D11 Linux驱动移植及内核深化 学习笔记

一、设备树 1.1 设备树 设备树是一种描述硬件信息的数据结构&#xff0c;Linux内核运行时可以通过设备树将硬件信息直接传递给Linux内核&#xff0c;而不再需要在Linux内核中包含大量的冗余编码 举例&#xff1a;让LED2闪烁的代码中&#xff0c;有逻辑代码和设备代码。Li…

案例121:基于微信小程序的作品集展示系统设计与实现

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

【模型评估 04】A/B测试的陷阱

互联网公司中&#xff0c;A/B测试是验证新模块、新功能、新产品是否有效&#xff1b;新算法、新模型的效果是否有提升&#xff1b;新设计是否受到用户欢迎&#xff1b;新更改是否影响用户体验的主要测试方法。在机器学习领域中&#xff0c;A/B测试是验证模型最终效果的主要手段…

C语言 - 最简单,最易懂的指针、引用讲解

一、变量、地址、变量值 二、直接上代码&#xff0c;一边看上图&#xff0c;一边讲解 #include <stdio.h>struct Hello {int a;int b; };int main() {struct Hello h;h.a 10;h.b 20;struct Hello *hp;hp &h;printf("1: h的地址是%d&#xff0c;hp地址是%d \…

stm32学习笔记:USART串口通信

1、串口通信协议&#xff08;简介软硬件规则&#xff09; 全双工&#xff1a;打电话。半双工&#xff1a;对讲机。单工&#xff1a;广播 时钟&#xff1a;I2C和SPI有单独的时钟线&#xff0c;所以它们是同步的&#xff0c;接收方可以在时钟信号的指引下进行采样。串口、CAN和…

docker完成redis 三主三从

文章目录 关闭防火墙启动docker后台服务新建6个docker容器redis实例创建并运行docker容器实例 进入容器redis-node-1并为6台机器构建集群关系链接进入6381作为切入点&#xff0c;查看集群状态主从容错切换迁移案例容错切换迁移 主从扩容案例为主节点6387分配从节点6388主从缩容…

一、MOJO环境部署和安装

以Ubuntu系统为例。 安装mojo-CLI curl https://get.modular.com | MODULAR_AUTHmut_fe303dc5ca504bc4867a1db20d897fd8 sh - 安装mojo SDK modular auth mojo modular auth install mojo 查看mojo版本号 mojo --version 输入mojo指令&#xff0c;进入交互编程窗口

On the Robustness of Backdoor-based Watermarkingin Deep Neural Networks

关于深度神经网络中基于后门的数字水印的鲁棒性 ABSTRACT 在过去的几年中&#xff0c;数字水印算法已被引入&#xff0c;用于保护深度学习模型免受未经授权的重新分发。我们调查了最新深度神经网络水印方案的鲁棒性和可靠性。我们专注于基于后门的水印技术&#xff0c;并提出了…

6、C语言:输入与输出

输入输出 标准输入输出getchar&putchar函数printf函数sprintf函数格式化输入——scanf函数 文件访问文件读写 错误处理&#xff1a;stderr和exit行输入和行输出常用函数字符串操作函数字符类别测试和转换函数存储管理函数数学函数随机数发生器函数其他 标准输入输出 getch…

2024年【氧化工艺】免费试题及氧化工艺作业模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 氧化工艺免费试题根据新氧化工艺考试大纲要求&#xff0c;安全生产模拟考试一点通将氧化工艺模拟考试试题进行汇编&#xff0c;组成一套氧化工艺全真模拟考试试题&#xff0c;学员可通过氧化工艺作业模拟考试全真模拟…

洛谷 P1439 【模板】最长公共子序列【线性dp+dp模型转换】

原题链接&#xff1a;https://www.luogu.com.cn/problem/P1439 题目描述 给出 1,2,…,n 的两个排列 P1​ 和 P2​ &#xff0c;求它们的最长公共子序列。 输入格式 第一行是一个数 n。 接下来两行&#xff0c;每行为 n 个数&#xff0c;为自然数 1,2,…,n 的一个排列。 输…

2023 年全国职业院校技能大赛(高职组) “云计算应用”赛项赛卷 B部分解析

2022 年全国职业院校技能大赛高职组云计算赛项试卷部分解析 【赛程名称】第一场&#xff1a;模块一 私有云、模块二 容器云【任务 1】私有云服务搭建[5 分]【题目 1】1.1.1 基础环境配置[0.2 分]【题目 2】1.1.2 Yum 源配置[0.2 分]【题目 3】1.1.3 配置无秘钥 ssh[0.2 分]【题…

Keil5如何生成反汇编文件

Keil5如何生成反汇编文件 在Keil5界面下点击选项&#xff0c;选择“User”&#xff0c;勾选“After Build/Rebuild”中“RUN #1”&#xff0c;复制fromelf --text -a -c --outputxxx.dis xxx.axf 在Linker栏中找到“Linker Control string”里最后-o后的.axf文件&#xff0c;将…

Linux:nginx设置网站https

http和https的区别 http: 80 https: 443 这种协议比http协议要安全&#xff0c;因为传输数据是经过加密的 HTTPS简介 HTTPS其实是有两部分组成&#xff1a;HTTP SSL / TLS&#xff0c;也就是在HTTP上又加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过…

Nginx的安装配置和使用

最近有好几个地方用到了nginx&#xff0c;但是一直还没时间记录下nginx的安装、配置和使用&#xff0c;这篇文章可以将这块内容整理出来&#xff0c;方便大家一起学习~ 安装 安装是相对简单一些的&#xff0c;直接使用yum即可。 yum install -y nginx 默认安装位置在/usr/sb…

Linux------进程的初步了解

目录 一、什么是进程 二、进程的标识符pid 三、getpid 得到进程的PID 四、kill 终止进程 五、父进程与子进程 六、目录中的进程 一、什么是进程 在windows中&#xff0c;我们查看进程很简单&#xff0c;打开任务管理器&#xff0c;就可以看到在运行的进程。这里我们还可以…

STM32H5 Nucleo-144 board开箱

文章目录 开发板资料下载 【目标】 点亮LD1&#xff08;绿&#xff09;、LD2&#xff08;黄&#xff09;和LD3&#xff08;红&#xff09;三个LED灯 【开箱过程】 博主使用的是STM32CubeMX配置生成代码&#xff0c;具体操作如下&#xff1a; 打开STM32CubeMX&#xff0c;File-…

Raspberry Pi 4B 蓝牙串口(SPP)配置与使用

Raspberry Pi 4B 蓝牙串口&#xff08;SPP&#xff09;配置与使用 文章目录 Raspberry Pi 4B 蓝牙串口&#xff08;SPP&#xff09;配置与使用1、蓝牙相关命令工具2、Linux中的蓝牙堆栈3、蓝牙串口配置4、蓝牙串口数据发送与接收 本文将详细介绍如何在Raspberry Pi 4B卡片电脑中…

快速入门java网络编程基础------Nio

一. NIO 基础 哔哩哔哩黑马程序员 netty实战视频 0.什么是nio&#xff1f; NIO&#xff08;New I/O&#xff09;是Java中提供的一种基于通道和缓冲区的I/O&#xff08;Input/Output&#xff09;模型。它是相对于传统的IO&#xff08;InputStream和OutputStream&#xff09;模型…

Spring boot - Task Execution and Scheduling @Async

SpringBoot的任务执行器 Spring Boot通过auto-configuration机制自动创建了任务执行器Task Execution&#xff0c;因此在SpringBoot项目中&#xff0c;你不需要任何配置、也不需要自己创建Task Execution就可以直接使用它。 Spring Boot通过auto-configuration机制创建的任务…