c++--------《set 和 map》

c++--------《set 和 map》

  • 1 set系列的使⽤
    • 1.1 set类的介绍
    • 1.2 set的构造和迭代器
    • 1.3 set重要接口
  • 2 实现样例
    • 2.1: insert和迭代器遍历使⽤样例:
    • 2.2: find和erase使⽤样例:
  • 练习
  • 3.map系列的使用
    • 3.1 map类的介绍
      • 3.1.1 pair类型介绍
    • 3.2 map的数据修改
    • 3.3multimap和map的差异
  • 结束!!!

1 set系列的使⽤

1.1 set类的介绍

• set的声明如下,T就是set底层关键字的类型• set默认要求T⽀持⼩于⽐较,如果不⽀持或者想按⾃⼰的需求⾛可以⾃⾏实现仿函数传给第⼆个模版参数• set底层存储数据的内存是从空间配置器申请的,如果需要可以⾃⼰实现内存池,传给第三个参数。• ⼀般情况下,我们都不需要传后两个模版参数。• set底层是⽤红⿊树实现,增删查效率是 ,迭代器遍历是⾛的搜索树的中序,所以是有序的。O(logN)• 前⾯部分我们已经学习了vector/list等容器的使⽤,STL容器接⼝设计,⾼度相似,所以这⾥我  们就不再⼀个接⼝⼀个接⼝的介绍,⽽是直接带着⼤家看⽂档,挑⽐较重要的接⼝进⾏介绍。
template < class T, // set::key_type/value_type类型
class Compare = less<T>, // set::key_compare/value_compare比较函数
class Alloc = allocator<T> // set::allocator_type 
> class set;

1.2 set的构造和迭代器

在这里插入图片描述

~empty(1) 无参构造   set()
~range(2) 迭代器构造 set(InputIterator first,InputIterator second)
~copy(3)  拷贝构造   set(const set& x)
~move(4) 移动构造    set(set&& x)
~initializer list(5) set({1,2,3,4,5})  
// empty (1) ⽆参默认构造
explicit set (const key_compare& comp = key_compare(),
const allocator_type& alloc = allocator_type());// range (2) 迭代器区间构造
template <class InputIterator>
set (InputIterator first, InputIterator last,
const key_compare& comp = key_compare(),
const allocator_type& = allocator_type());// copy (3) 拷⻉构造
set (const set& x);// initializer list (5) initializer 列表构造
set (initializer_list<value_type> il,
const key_compare& comp = key_compare(),
const allocator_type& alloc = allocator_type());// 迭代器是⼀个双向迭代器
iterator -> a bidirectional iterator to const value_type// 正向迭代器
iterator begin();
iterator end();// 反向迭代器
reverse_iterator rbegin();
reverse_iterator rend();

1.3 set重要接口

1: insert (插入元素)

// 单个数据插⼊,如果已经存在则插⼊失败,bool返回false
pair<iterator,bool> insert (const value_type& val);//初始化列表插入,已经在容器中存在的值不会插入
void insert(initializer_list<value_type> x)//迭代器区间插入,如果已经存在的值就不会插入
template<class InputIterator>
void insert(InputIterator first,InputIterator last);

2:find(查找元素)

//查找val,返回val所在的迭代器,没有找到返回end()iterator find(const value_type& val);

3:count (查找元素个数)

//查找val,返回val的个数
size_type count(const value_type& val) const;

4:erase(删除元素)

// 删除⼀个迭代器位置的值
iterator erase (const_iterator position);// 删除val,val不存在返回0,存在返回1
size_type erase (const value_type& val);// 删除⼀段迭代器区间的值
iterator erase (const_iterator first, const_iterator last);

5:lower_bound 和 upper_bound
返回(upper_bound)的大于val的迭代器
返回(lower_bound)的大于等于val的迭代器

// 返回⼤于等val位置的迭代器
iterator lower_bound (const value_type& val) const;// 返回⼤于val位置的迭代器
iterator upper_bound (const value_type& val) const;

2 实现样例

2.1: insert和迭代器遍历使⽤样例:

#include<iostream>
#include<set>
using namespace std;
int main()
{
// 去重+升序排序
set<int> s;
// 去重+降序排序(给⼀个⼤于的仿函数)
//set<int, greater<int>> s;
s.insert(4);
s.insert(3);
s.insert(65);
s.insert(8);
//set<int>::iterator it = s.begin();
auto it = s.begin();
while (it != s.end())
{
// error C3892: “it”: 不能给常量赋值
// *it = 1;//数据不能被修改
cout << *it << " ";
++it;
}
cout << endl;
// 插⼊⼀段initializer_list列表值,已经存在的值插⼊失败
s.insert({ 2,8,3,9 });
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
set<string> strset = { "sort", "insert", "add" };
// 遍历string⽐较ascll码⼤⼩顺序遍历的
for (auto& e : strset)
{
cout << e << " ";
}
cout << endl;
}

【注意】
如果可以改变比较大小顺序 greater降序 ,默认是升序

set<string,greater<string>> strset = { "sort", "insert", "add" };
// 遍历string⽐较ascll码⼤⼩顺序遍历的
for (auto& e : strset)
{
cout << e << " ";
}
cout << endl;
}

在这里插入图片描述

2.2: find和erase使⽤样例:

#include<iostream>
#include<set>
using namespace std;
int main()
{
set<int> s = { 4,2,7,2,8,5,9 };
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
// 删除最⼩值
s.erase(s.begin());
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
// 直接删除x
int x;
cin >> x;
int num = s.erase(x);
if (num == 0)
{
cout << x << "不存在!" << endl;
}
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
// 直接查找在利⽤迭代器删除x
cin >> x;
auto pos = s.find(x);
if (pos != s.end())
{
s.erase(pos);
}
else
{
cout << x << "不存在!" << endl;
}
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
// 算法库的查找 O(N)
auto pos1 = find(s.begin(), s.end(), x);
// set⾃⾝实现的查找 O(logN)
auto pos2 = s.find(x);
// 利⽤count间接实现快速查找
cin >> x;
if (s.count(x))
{
cout << x << "在!" << endl;
}
else
{
cout << x << "不存在!" << endl;
}
return 0;
}#include<iostream>
#include<set>
using namespace std;
int main()
{
std::set<int> myset;
for (int i = 1; i < 10; i++)
myset.insert(i * 10); // 10 20 30 40 50 60 70 80 90
for (auto e : myset)
{
cout << e << " ";
}
cout << endl;
// 实现查找到的[itlow,itup)包含[30, 60]区间
// 返回 >= 30
auto itlow = myset.lower_bound(30);
// 返回 > 60
auto itup = myset.upper_bound(60);
// 删除这段区间的值
myset.erase(itlow, itup);
for (auto e : myset)
{
cout << e << " ";
}
cout << endl;
return 0;
}

对于erase来说,删除后迭代器会失效

练习

1: 俩个数组的交集

利用set的性质(避免多个数据重复)可以很好解决此问题
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());
// 因为set遍历是有序的,有序值,依次⽐较
// ⼩的++,相等的就是交集
vector<int> ret;
auto it1 = s1.begin();
auto it2 = s2.begin();
while(it1 != s1.end() && it2 != s2.end())
{
if(*it1 < *it2)
{
it1++;
}
else if(*it1 > *it2)
{
it2++;
}
else
{
ret.push_back(*it1);
it1++;
it2++;
}
}
return ret;
}
};

2:环形链表

 利用接口count可以解决环形链表问题
class Solution {
public:ListNode *detectCycle(ListNode *head) {set<ListNode*> s;ListNode* cur=head;while(cur){if(s.count(cur))//s.count(cur)是判断有无cur的值{return cur;}else s.insert(cur);cur=cur->next;} return nullptr;}
};

随机链表复制

class Solution {
public:Node* copyRandomList(Node* head) {Node* copyhead=nullptr;Node* copytail=nullptr;Node* cur=head;map<Node*,Node*> s;while(cur)//结点映射拷贝{ if(copytail==nullptr){copyhead=copytail= new Node(cur->val);}else{copytail->next=new Node(cur->val);copytail=copytail->next;}s[cur]=copytail;//结点映射 cur->random cur=cur->next;}cur=head;Node* copy=copyhead;
while(cur)//random复制{if(cur->random==nullptr){copy->random=nullptr;}else{copy->random=s[cur->random];}cur=cur->next;    copy=copy->next;}return copyhead;}
};

3.map系列的使用

3.1 map类的介绍

map的声明如下,Key就是map底层关键字的类型,T是map底层value的类型,set默认要求Key⽀持⼩于⽐较,如果不⽀持或者需要的话可以⾃⾏实现仿函数传给第⼆个模版参数,map底层存储数据的内存是从空间配置器申请的。⼀般情况下,我们都不需要传后两个模版参数。map底层是⽤红⿊树实现,增删查改效率是 O(logN) ,迭代器遍历是⾛的中序,所以是按key有序顺序遍历的。

//Key就是map底层关键字的类型,T是map底层value的类型,
template < class Key, // map::key_type
class T, // map::mapped_type
class Compare = less<Key>, // map::key_compare
class Alloc = allocator<pair<const Key,T> > //
map::allocator_type> class map;

3.1.1 pair类型介绍

pair类型是用struct 封装的类,有俩个值key或value
typedef pair<const Key, T> value_type;
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)
{}
template<class U, class V>
pair (const pair<U,V>& pr): first(pr.first), second(pr.second)
{}
};

3.2 map的数据修改

map的构造与set的构造,和接口都差不多

增删查改

Insert
在这里插入图片描述

对于insert的返回值pair<iterator,bool>
(1) single element  给值插入(2) with hint 指定位置插入(3) range 迭代器区间插入(4)initializer list 初始化插入1:对于插入失败,则返回pair<iterator,false>,返回false
2:对于迭代器iterator,返回值iterator是返回插入时的迭代器
// 单个数据插⼊,如果已经key存在则插⼊失败,key存在相等value不相等也会插⼊失败
pair<iterator,bool> insert (const value_type& val);// 列表插⼊,已经在容器中存在的值不会插⼊
void insert (initializer_list<value_type> il);// 迭代器区间插⼊,已经在容器中存在的值不会插⼊
template <class InputIterator>
void insert (InputIterator first, InputIterator last);

erase
在这里插入图片描述

对于erase返回值:
1:iterator 返回的是删除的迭代器2:size_type 是返回删除的个数对于参数
1:const iterator position 是 指定区间删除2:const key_type& k 指定值删除3: 迭代器区间删除
// 删除⼀个迭代器位置的值
iterator erase (const_iterator position);// 删除k,k存在返回0,存在返回1
size_type erase (const key_type& k);// 删除⼀段迭代器区间的值
iterator erase (const_iterator first, const_iterator last);

find、count
在这里插入图片描述
在这里插入图片描述

iterator find (const key_type& k);
// 查找k,返回k的个数
size_type count (const key_type& k) const;

operator[ ] ()

功能增 查 改
在这里插入图片描述

map的operator【】,给key会返回value,如果key不存在的时候,
1:如果有就会修改second、2: key 不存在就插入

1、如果k不在map中,insert会插⼊k和mapped_type默认值,同时[]返回结点中存储
mapped_type值的引⽤,那么我们可以通过引⽤修改返映射值。所以[]具备了插⼊+修改功能
2、如果k在map中,insert会插⼊失败,但是insert返回pair对象的first是指向key结点的迭代器,返回值同时[]返回结点中存储mapped_type值的引⽤,所以[]具备了查找+修改的功能.

数据修改

前⾯我提到map⽀持修改mapped_type 数据,不⽀持修改key数据,修改关键字数据,破坏了底层搜索树的结构。map第⼀个⽀持修改的⽅式时通过迭代器,迭代器遍历时或者find返回key所在的iterator修改,map还有⼀个⾮常重要的修改接⼝operator[],但是operator[]不仅仅⽀持修改,还⽀持插⼊数据和查找数据,所以他是⼀个多功能复合接⼝需要注意从内部实现⻆度,map这⾥把我们传统说的value值,给的是T类型,typedef为mapped_type。⽽value_type是红⿊树结点中存储的pair键值对值。⽇常使⽤我们还是习惯将这⾥的T映射值叫做value。

【注意】

1、如果key已经在map中,插⼊失败,则返回⼀个pair<iterator,bool>对象,返回pair对象first是key所在结点的迭代器,second是false
2、如果key不在在map中,插⼊成功,则返回⼀个pair<iterator,bool>对象,返回pair对象first是新插⼊key所在结点的迭代器,second是true
3、也就是说⽆论插⼊成功还是失败,返回pair<iterator,bool>对象的first都会指向key所在的迭代器
4、那么也就意味着insert插⼊失败时充当了查找的功能,正是因为这⼀点,insert可以⽤来实现operator[]

3.3multimap和map的差异

multimap和map的使⽤基本完全类似,主要区别点在于multimap⽀持关键值key冗余,那么insert/find/count/erase都围绕着⽀持关键值key冗余有所差异,这⾥跟set和multiset完全⼀样,⽐如find时,有多个key,返回中序第⼀个。其次就是multimap不⽀持[],因为⽀持key冗余,[]就只能⽀持插⼊了,不能⽀持修改。

结束!!!

压力不是有人比你努力,而是比你牛叉几倍的人依然在努力。每个优秀的人,都有一段沉默的时光继承就讲到这里谢谢大家的观看!!!

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

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

相关文章

GIS融合之路(八)-如何用Cesium直接加载OSGB文件(不用转换成3dtiles)

系列传送门&#xff1a; 山海鲸可视化&#xff1a;GIS融合之路&#xff08;一&#xff09;技术选型CesiumJS/loaders.gl/iTowns? 山海鲸可视化&#xff1a;GIS融合之路&#xff08;二&#xff09;CesiumJS和ThreeJS深度缓冲区整合 山海鲸可视化&#xff1a;GIS融合之路&…

cooper+隐含数+2元cooper

发现群里一个题&#xff0c;应该是几天前一个比赛的。作了一下午。 from Crypto.Util.number import * import os from hashlib import * from random import * p getPrime(512) q getPrime(512) n p*q m bytes_to_long(os.urandom(20)) x pow(m,p,n) y pow(m,q,n)with…

QQ 小程序已发布,但无法被搜索的解决方案

前言 我的 QQ 小程序在 2024 年 8 月就已经审核通过&#xff0c;上架后却一直无法被搜索到。打开后&#xff0c;再在 QQ 上下拉查看 “最近使用”&#xff0c;发现他出现一下又马上消失。 上线是按正常流程走的&#xff0c;开发、备案、审核&#xff0c;没有任何违规&#xf…

word 中长公式换行 / 对齐 | Mathtype 中长公式换行拆分 | latex 中长公式换行

注&#xff1a;本文为 “word 中长公式换行 / 对齐 | Mathtype 中长公式换行拆分 | latex 中长公式换行” 相关专题文章合辑。 未整理去重。 “公式较长时最好在等号 “&#xff1d;” 处转行&#xff0c;如难实现&#xff0c;则可在&#xff0b;、&#xff0d;、、 运算符号处…

【优选算法 — 滑动窗口】串联所有单词的子串 最小覆盖子串

串联所有单词的子串 串联所有单词的子串 题目描述 题目解析 算法原理 以示例一为例&#xff0c;一定要记得&#xff0c;words中的每一个字符串长度相同&#xff0c;所以我们可以根据 words 中的每一个字符串的长度length&#xff0c;将 s 这个字符串以 length 个为一组来…

了解 Solon MVC 的参数注入规则

关于 Solon MVC 参数注入&#xff0c;主要尊守以下基本规则&#xff1a; 参数名与请求数据名一一对应。当对上不上时&#xff0c;会采用整体数据注入&#xff08;如果接收的是实体&#xff09;参数名与请求数据同名时&#xff0c;又想整体注入&#xff08;如果接收的是实体&am…

[SpB]如何开始使用 Spring Boot?

如何开始使用 Spring Boot&#xff1f; Spring Boot 简化了 Java 项目开发&#xff0c;你只需要专注于业务逻辑&#xff0c;底层的很多配置和功能由 Spring Boot 自动帮你处理。下面是你如何快速上手 Spring Boot 的步骤&#xff0c;以及如何通过 IDEA 了解 Spring Boot 的功能…

vue如何实现组件切换

一、使用条件渲染 (v-if) <template><div><button click"currentView ComponentA">Show Component A</button><button click"currentView ComponentB">Show Component B</button><component-a v-if"curren…

WEB攻防-通用漏洞SQL注入sqlmapOracleMongodbDB2等

SQL注入课程体系&#xff1a; 1、数据库注入-access mysql mssql oracle mongodb postgresql 2、数据类型注入-数字型 字符型 搜索型 加密型&#xff08;base64 json等&#xff09; 3、提交方式注入-get post cookie http头等 4、查询方式注入-查询 增加 删除 更新 堆叠等 …

7.揭秘C语言输入输出内幕:printf与scanf的深度剖析

揭秘C语言输入输出内幕&#xff1a;printf与scanf的深度剖析 C语言往期系列文章目录 往期回顾&#xff1a; VS 2022 社区版C语言的安装教程&#xff0c;不要再卡在下载0B/s啦C语言入门&#xff1a;解锁基础概念&#xff0c;动手实现首个C程序C语言概念之旅&#xff1a;解锁关…

SHELL(4)脚本与用户交互以及if条件判断

声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&a…

Springboot集成ElasticSearch实现minio文件内容全文检索

一、docker安装Elasticsearch &#xff08;1&#xff09;springboot和Elasticsearch的版本对应关系如下&#xff0c;请看版本对应&#xff1a; 注意安装对应版本&#xff0c;否则可能会出现一些未知的错误。 &#xff08;2&#xff09;拉取镜像 docker pull elasticsearch:7…

部分利用oracle数据字典查询对应信息的语句。

查看当前用户的缺省表空间 SQL>select username,default_tablespace from user_users; 查看当前用户的角色 SQL>select * from user_role_privs; 查看当前用户的系统权限和表级权限 SQL>select * from user_sys_privs; SQL>select * from user_tab_privs; …

#Ts篇: ts学习再梳理

ts类型梳理 类型声明的写法&#xff0c;一律为在标识符后面添加“冒号 类型”。函数参数和返回值&#xff0c;也是这样来声明类型。 function toString(num: number): string {return String(num); }上面示例中&#xff0c;函数toString()的参数num的类型是number。参数列表…

使用chrome 访问虚拟机Apache2 的默认页面,出现了ERR_ADDRESS_UNREACHABLE这个鸟问题

本地环境 主机MacOs Sequoia 15.1虚拟机Parallels Desktop 20 for Mac Pro Edition 版本 20.0.1 (55659)虚拟机-操作系统Ubuntu 22.04 服务器版本 最小安装 开发环境 编辑器编译器调试工具数据库http服务web开发防火墙Vim9Gcc13Gdb14Mysql8Apache2Php8.3Iptables 第一坑 数…

定时器的小应用

第一个项目 第一步&#xff0c;RCC开启时钟&#xff0c;这个基本上每个代码都是第一步&#xff0c;不用多想&#xff0c;在这里打开时钟后&#xff0c;定时器的基准时钟和整个外设的工作时钟就都会同时打开了 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);第二步&…

【工控】线扫相机小结 第三篇

海康软件更新 目前使用的是 MVS_STD_4.3.2_240705.exe &#xff0c;最新的已经到4.4了。 一个大的变动 在上一篇中我们提到一个问题&#xff1a; 需要注意的是&#xff0c;我们必须先设置 TriggerSelector 是 “FrameBurstStart” 还是 “LineStart” 再设置TriggerMode 是 …

零基础利用实战项目学会Pytorch

目录 pytorch简介 1.线性回归 2.数据类型 2.1数据类型检验 2.2Dimension0/Rank0 2.3 Dim1/Rank1 2.4 Dim2/Rank2 3.一些方法 4.Pytorch完成分类任务 4.1模型参数 4.2 前向传播 4.3训练以及验证 4.4 三行搞定&#xff01; 4.5 准确率 5、Pytorch完成回归任务 5.…

MySQL的游标和While循环的详细对比

MySQL游标和While循环的详细对比 在 MySQL 中&#xff0c;游标和 WHILE 循环是两种常用的处理结果集的机制。它们各自有不同的应用场景和特点。本文将详细对比这两种机制&#xff0c;并提供具体的示例代码和说明。 1. 游标&#xff08;Cursor&#xff09; 游标是一种数据库对…

【#IEEE独立出版、EI稳定检索##高录用 快见刊 稳检索#】2024健康大数据与智能医疗国际会议(ICHIH 2024,12月13-15日)

#IEEE独立出版、EI稳定检索# #往届快至会后3-4个月检索# #高录用 快见刊 稳检索# 2024健康大数据与智能医疗国际会议&#xff08;ICHIH 2024&#xff09; 2024 International Conference on Health Big Data and Intelligent Healthcare 重要信息 大会官网&#xff1a;ww…