算法学习入门--- set与map(C++)

算法学习入门--- set与map(C++)

目录

1.set、multiset介绍

2.map、multimap介绍

3.洛谷---英语1(eng1)- 英语作文

4.洛谷--- [HNOI2002] 营业额统计

5.洛谷---【深基17.例5】木材仓库


1.set、multiset介绍

  • set不能存相同元素,multiset能存相同元素,存10个1前者只会存1个1,后者会存10个1,除此以外所有的函数功能相同。所以,set是具有去重的功能的
  • 创建格式:set<type> mp1 
  • size:返回实际元素个数
  • empty:返回是否为空
  • begin、end:可以使用for遍历整个set(红黑树),遍历时按照中序遍历来遍历的,根据红黑树的性质,遍历结果会是一个有序的序列;begin表示的是第一个元素的迭代器,end表示的是最后一个元素之后的迭代器,所以遍历范围为 [begin,end);迭代器作为一个抽象化的指针(无法被直接访问的指针,即无法cout其地址),无法通过 < 来和 end迭代器 比较,所以必须要使用 it != mp.end()
  • insert:插入一个元素,O(logN)
  • erase:删除一个元素,O(logN)
  • find:查找一个元素,返回的是迭代器,如果没找到就返回set.end(),O(logN)
  • count:查询元素出现的次数,因为set中的元素唯一,所以只会返回1(存在)或0(不存在),一般用来查询元素是否在红黑树中,O(logN)
  • lower_bound:大于等于x的最小元素,返回的是迭代器
  • upper_bound:大于x的最小元素,返回的是迭代器

代码演示:

#include<iostream> #include<set> using namespace std; int a[]={10,10,60,20,70,80,30,90,40,100,50}; int main() { set<int> mp; for(auto x:a)mp.insert(x); //for(auto it = mp.begin();it != mp.end();it++) //cout<<*it<<" "; for(auto x:mp)cout<<x<<" "; cout<<endl; mp.erase(60); mp.erase(100); for(auto x:mp)cout<<x<<" "; cout<<endl; if(mp.count(10))cout<<"Yes"<<" "; else cout<<"No"<<" "; if(mp.count(1))cout<<"Yes"<<" "; else cout<<"No"<<" "; cout<<endl; auto x = mp.lower_bound(20); auto y = mp.upper_bound(20); cout<<*x<<" "<<*y; return 0; }

2.map、multimap介绍

  • map相当于set当中存取的数据为pair类型
  • map当中,比较方式是以key来做比较的,换言之遍历map时,中序遍历的是key而不是key所对应的value;map只允许一个键对应一个值,multimap允许一个键对应多个值
  • 创建格式:map<type,type> mp1
  • size、empty、begin、end与上同,不解释
  • insert:插入的元素为键值对,insert({1,2})
  • operator[]:重载[],使得map可以像数组一样使用,并且重载[]这一步操作C++提供的模板已经帮我们搞好了,直接用即可;但使用[]访问map时,会把不存在于map当中的键值对插入进去,并给键所对应的值赋上一个0;为了防止这个情况发生,可以先count一下看看这个键值对是否存在,然后再使用[]访问
  • erase:删除一个元素,传入key即可删除
  • count:查看一个元素是否存在,传入key即可
  • lower_bound,upper_bound:比较的是传入值与键的大小,其他与set不变

代码演示:

#include<iostream> #include<map> using namespace std; void print(map<string,int>& mp) { for(auto& p:mp) cout<<p.first<<" "<<p.second<<endl; } int main() { map<string,int> mp; mp.insert({"zhang",1}); mp.insert({"lisi",2}); mp.insert({"wang",3}); print(mp); cout<<mp["zhang"]<<endl; if(mp["zhao"]==4)cout<<"yes"<<endl; //if(mp.count("zhao")&&mp["zhao"]==4)cout<<"yes"<<endl; else cout<<"no"<<endl; print(mp); mp.erase("zhao"); print(mp); return 0; }

3.洛谷---英语1(eng1)- 英语作文

为了方便截取单词,需要以字符的格式读取,并以输入的非单词字符作为分割;如果以字符串读取,就需要我们自己来截取单词,比较麻烦

在c++中,string类型字符串重新赋空的代码为

map的键值对代表的是<高级词汇,词汇分数>

代码:

#include<iostream> #include<map> #include<cstdio> using namespace std; #define int long long signed main() { int N,P;cin>>N>>P; map<string,int> sc;//词汇和成绩对照表 while(N--) { string in;int num;cin>>in>>num; sc.insert({in,num}); } string word; char cur; int ret=0; while(scanf("%c",&cur)!=EOF)//while((cur=getchar())!=EOF) { if((cur>='a'&&cur<='z')||(cur>='A'&&cur<='Z')||(cur>='0'&&cur<='9'))//单词输入 word+=cur; else { if(sc.count(word)) ret+=sc[word];;//说明一个单词结束了 } } cout<<(ret%P); return 0; }
代码易错点:

cin遇到空格时会自动跳过,那么空格分隔的特性就失效了

scanf虽然%s读取会省略空白字符,但%c读取不会;getchar读取失败时和scanf一样,返回EOF;scanf返回值为一个整数,表示成功读取的变量个数(占位符与输入数据格式不匹配也算失败读取),一个变量都没有成功读取发生错误则返回EOF(-1),如果全都只是占位符与输入数据格式不匹配那么返回0

4.洛谷--- [HNOI2002] 营业额统计

对于第i天的营业额来说,就是从[0,i-1]范围中找到和他相差最小的那个元素

例如当前元素为4 ,从1 2 5 7 8 9 当中寻找,那么找到的那个数是比他要大的5,此处视作y

例如当前元素为3,从1 2 5 7 8 9 当中寻找,那么找到的那个书是比他要小的2,此处视作z

最终获得的波动值应该为min(|y-x|,|z-x|)

寻找大于等于x的最小值时,使用lower-bound即可

当序列有序时,迭代器it--以后,就能获得小于等于x的最大值

对于红黑树遍历来说,因为是有序的,所以可以直接it--,不需要再对其进行排序,但需要注意的是:不能*(it-1),只能it--后再对it进行解引用,换言之只能让迭代器变化位置,但不能对迭代器进行指针运算

当x正好大于等于set中的第一个元素,那么it--可能会存在越界访问的情况,此时可以初始化给到一个左右护法,即整个set的前面加上一个-∞,整个set的后面加上一个+∞,那么就不会再有越界访问的情况(如下图所示)

正确性检验:无论是it所指向的元素多小,最要比代表-∞的值要大,这个-∞的值可以取为-1e7,+∞也是这样判断的

代码:

#include<iostream> #include<set> #include<algorithm> #include<cmath> using namespace std; #define int long long signed main() { int d;cin>>d; set<int> mp; //第一次为特殊情况 int fst,ret=0;cin>>fst; mp.insert(fst);ret+=fst;d--; mp.insert(1e7); mp.insert(-1e7); while(d--) { int in;cin>>in; auto it = mp.lower_bound(in);int y = *it; it--;int z = *it; ret+=min(abs(y-in),abs(z-in)); mp.insert(in); } cout<<ret; return 0; }

5.洛谷---【深基17.例5】木材仓库

代码:

#include<iostream> #include<set> #include<cmath> using namespace std; #define int long long signed main() { int m;cin>>m; set<int> mp; mp.insert(1e10); mp.insert(-1e10); while(m--) { int flag,len;cin>>flag>>len; if(flag==1) { //先判断在仓库中是否存在 if(mp.count(len))cout<<"Already Exist"<<endl; mp.insert(len); } else { //仓库为空 if(mp.size()==2) { cout<<"Empty"<<endl; continue; } //开始寻找差值最小的木材 auto it = mp.lower_bound(len);int y = *it; it--;int z = *it; if(abs(y-len)>=abs(z-len)) { cout<<z<<endl; mp.erase(z); } else { cout<<y<<endl; mp.erase(y); } } } return 0; }

Read more

基于大数据爬虫+Python+SpringBoot+Hive的网络电视剧收视率分析与可视化平台系统(源码+论文+PPT+部署文档教程等)

基于大数据爬虫+Python+SpringBoot+Hive的网络电视剧收视率分析与可视化平台系统(源码+论文+PPT+部署文档教程等)

博主介绍:ZEEKLOG毕设辅导第一人、全网粉丝50W+,ZEEKLOG特邀作者、博客专家、腾讯云社区合作讲师、ZEEKLOG新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文降重、长期答辩答疑辅导、腾讯会议一对一专业讲解辅导答辩、模拟答辩演练、和理解代码逻辑思路。 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇🏻 不然下次找不到哟 2022-2024年最全的计算机软件毕业设计选题大全:

By Ne0inhk
异步编程实战:构建高性能Python网络应用

异步编程实战:构建高性能Python网络应用

目录 摘要 1 异步编程:为什么它是现代网络应用的必然选择 1.1 同步架构的瓶颈与异步架构的优势 2 核心技术原理深度解析 2.1 asyncio事件循环:异步编程的发动机 2.2 aiohttp框架架构解析 3 异步数据库驱动实战 3.1 异步数据库连接池管理 3.2 多数据库支持与连接池优化 4 WebSocket实时通信实战 4.1 构建高性能WebSocket服务器 4.2 实时数据推送与流处理 5 企业级实战案例 5.1 构建异步API网关 6 性能优化与故障排查 6.1 性能优化实战技巧 6.2 常见故障排查指南 7 总结与展望 7.1

By Ne0inhk

【超详细】Python FastAPI 入门:写给新手的“保姆级”教程

【超详细】Python FastAPI 入门:写给新手的“保姆级”教程(2025–2026 最新版) 这篇教程的目标是: 零基础 → 能独立写出生产级别的 RESTful API 预计认真跟着做完前 80%,你大概需要 3–10 天(每天 2–4 小时)。 目录(建议按顺序阅读) 1. 为什么选择 FastAPI(而不是 Flask / Django) 2. 环境准备(最稳的几种方式) 3. 第一个 FastAPI 程序(Hello World) 4. 核心概念速览(5 分钟建立大局观) 5. 路径参数、查询参数、请求体(

By Ne0inhk
【超详细】Python FastAPI 入门:写给新手的“保姆级”教程

【超详细】Python FastAPI 入门:写给新手的“保姆级”教程

前言  作为一名大学生,最近在做 Python Web 开发时发现了一个“宝藏”框架——FastAPI。 以前学 Django 光配置就头大,学 Flask 又不知道怎么写规范。直到遇到了 FastAPI,我才体会到什么叫“写代码像呼吸一样自然”。 这篇文章不讲复杂的原理,只讲最基础、最实用的操作,带你从 0 到 1 跑通第一个 API 接口! 一、FastAPI 是什么 在 Python 的世界里,做网站后台(Web 开发)主要有三巨头: 1. Django:老大哥,功能全但笨重,像一辆重型卡车。 2. Flask:二哥,轻便灵活但插件多,像一辆自行组装的赛车。 3.

By Ne0inhk