map和set的使用(一)详解

文章目录

  • 序列式容器和关联式容器
  • map和set的介绍
  • set
    • 构造和迭代器遍历和insert
    • find
    • erase
    • swap
    • clear
    • count
    • lower_bound和upper_bound
    • multiset和set的对比
  • set的二个题目
    • 题目解析
    • 算法原理
    • 代码
    • 介绍一个找差集的算法
    • 同步算法
    • 题目解析
    • 算法原理
    • 代码
  • map
    • 构造
    • 遍历
    • initiaizer_list

序列式容器和关联式容器

  • 序列式容器在逻辑上是线性的,在物理上不一定连续,它们的数据之间没有太大的关联,比如交换两个位置的数,依旧是序列式容器,比如vector,list,deque等
  • 关联式容器在逻辑上是非线性的,两个位置的关系是紧密相关的,比如二叉搜索树,随意交换两个位置就破坏了这棵树的结构

map和set的介绍

map和set底层是红黑树,红黑树是平衡二叉搜索树,平衡二叉搜索树接近完全二叉树的结构,但不是完全二叉树,查找效率提高了,等于logN次,set是key的场景,map是key/value的场景。

set

支持增删查,不支持改,修改会改变树的性质

构造和迭代器遍历和insert

在这里插入图片描述

int main()
{// 降序排序+去重 Greater > set<int, greater<int>> t;// 升序排序+去重 Less <// set<int> t;t.insert(5);t.insert(7);t.insert(2);t.insert(5);// set<int>::iterator it = t.begin();auto it = t.begin();while(it != t.end()){// set不管什么迭代器都不支持修改// 修改会改变其内部结构// 按二叉搜索树的排序,中序,升序排序// *it = 10;cout << *it << " ";++it;}cout << endl;// initializer list 相同的值会插入失败t.insert({ 1,2,9,2,7 });for (auto e : t){cout << e << " ";}cout << endl;// void insert(initializer_list<value_type> ls);set<string> strset = { "sort","insert","add" };// 语法上隐式类型转换生成临时对象,临时对象拷贝构造strset// 编译器直接优化为构造// set<string> strset({ "sort","insert","add" });// 语法上构造for (auto& e : strset){cout << e << " ";}cout << endl;return 0;
}

find

在这里插入图片描述

// 算法库的find O(N)
auto pos = find(t.begin(), t.end(), x);
// set的find O(logN)
auto pos = t.find(x);

erase

在这里插入图片描述

  1. 删除某个位置的迭代器
  2. 删除某个值,返回成功删除数据的个数,删除失败返回0,为了兼容multiset(有数据冗余的set),这里面有多个相同的x
  3. 删除迭代器区间
    迭代器失效:
    1.删除的是根节点或只有一个孩子的节点,父亲节点已经链接其他节点了,去访问删除的节点是野指针,节点已经变了,意义变了
    2.删除的节点是有两个孩子的节点,替代法删除,把替代的节点删除,原来要删的节点的位置的迭代器失效,访问会崩溃,节点已经变了,意义变了
    在这里插入图片描述
int main()
{// 1.删除某个位置的迭代器set<int> t = { 1,2,93,403,43 };for (auto e : t){cout << e << " ";}cout << endl;// 删除最小值 [first,end),升序排序t.erase(t.begin());for (auto e : t){cout << e << " ";}cout << endl;// 2.删除某个值int x;/*cin >> x;int num = t.erase(x);if (num == 0){cout << num << "不存在" << endl;}else{cout << num << "删除成功" << endl;}cout << endl;for (auto e : t){cout << e << " ";}cout << endl;*/// 3.删除一个迭代器区间cin >> x;auto pos = t.find(x);if(pos != t.end()){// 删除这个节点后,该点迭代器失效t.erase(pos);// 不要访问,vs强制检查会崩溃cout << *pos << endl;// 访问Node节点}else{cout << "不存在" << endl;}for (auto e : t){cout << e << " ";}cout << endl;return 0;
}

swap

交换两个树的根节点
在这里插入图片描述

clear

清掉数据不清空间
在这里插入图片描述

count

value_type其实是为multiset准备的
功能:这个值在的话返回1,不在返回0
在这里插入图片描述

cin >> x;
if (t.count(x))
{cout << x << "在" << endl;
}
else
{cout << x << "不在" << endl;
}

lower_bound和upper_bound

lower_bound和upper_bound底层是按照二叉搜索树的逻辑进行查找的,logN
在这里插入图片描述

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; 返回 >= 30//auto lowit = myset.lower_bound(30); 返回 > 50//auto upit = myset.upper_bound(50); 30 40 50 // 返回 >= 25auto lowit = myset.lower_bound(25);// 返回 > 55auto upit = myset.upper_bound(55);// 30 40 50 // 删除这段区间的值, 迭代器区间的都是[)myset.erase(lowit, upit);for (auto e : myset){cout << e << " ";}cout << endl;return 0;
}

multiset和set的对比

  • multiset和set都在set头文件下,multiset允许键值冗余,insert/find/count/erase都围绕着支持值冗余有所差异
    在这里插入图片描述
int main()
{// 排序但是不去重multiset<int> t = { 1,2,1,2,342 };auto it = t.begin();while (it != t.end()){cout << *it << " ";++it;}cout << endl; 有多个x的话,find查找的是中序的第一个int x;cin >> x;//auto pos = t.find(x);//while (pos != t.end() && *pos == x)//{//	cout << *pos << " ";//	++pos;//}//cout << endl;//auto pos = t.find(x);//while (pos != t.end() && *pos == x)//{//	pos = t.erase(pos);//	// 删除后返回当前位置的下一个迭代器//}//cout << endl;cout << t.count(x) << endl;t.erase(x);// erase把所有x都删除it = t.begin();while (it != t.end()){cout << *it << " ";++it;}cout << endl;// 返回x的个数cout << t.count(x) << endl;return 0;
}

set的二个题目

题目链接

题目解析

在这里插入图片描述

算法原理

在这里插入图片描述

代码

class Solution 
{
public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {// 用set进行去重+排序set<int> s1(nums1.begin(),nums1.end());set<int> s2(nums2.begin(),nums2.end());vector<int> ret;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;}
};

介绍一个找差集的算法

差集:是一个集合有,另一个集合没有的数据(去除两个集合共同有的数据)
在这里插入图片描述

同步算法

在这里插入图片描述

题目解析

题目链接
在这里插入图片描述

算法原理

让节点一个一个地插入set中,如果set中第一次存在一个重复的节点的话,返回这个重复的节点就是循环的开始
在这里插入图片描述

代码

class Solution 
{
public:ListNode *detectCycle(ListNode *head) {set<ListNode*> p;ListNode* cur = head;while(cur){if(p.count(cur))return cur;elsep.insert(cur);cur = cur->next;}return nullptr;}
};

map

map也有map和multimap之分
map支持修改,但是修改的是value的值,迭代器也支持修改value
key->key
T->value
在二叉搜索树那里就是把两个参数分开放
在map这里是把两个参数放在一个pair中,封装了一层
第一个参数是key,第二个参数是value
在这里插入图片描述

构造

在这里插入图片描述

int main()
{// 1.构造对象pair插入dict(有名对象)map<string, string> dict;pair<string, string> kv1("auto", "一");dict.insert(kv1);// 2.匿名对象dict.insert(pair<string, string>("string", "二"));// 3.make_pair模版dict.insert(make_pair("vector", "三"));// 4.C++11dict.insert({ "map","三" });// 插入时只看key,value不相等时不会更新// key相等时插入失败,map是不允许冗余的dict.insert({ "map","三二" });return 0;
}

遍历

结构体指针用->
对象用 .
map不允许冗余,unordered_map允许冗余

map<string, string>::iterator it = dict.begin();
while (it != dict.end())
{// 只支持修改value,不支持修改key// first不支持修改// 底层存的是const first // 这里是const string// it->first += 'x';it->second += 'x';// map不支持*it// cout << *it << " ";// cout << (*it).first << ":" << (*it).second << endl;cout << it->first << ":" << it->second << endl;//cout << it.operator->()->first << ":" << it.operator->()->second << endl;// operator* 返回数据的引用 pair// operator-> 返回数据的指针 pair*++it;
}
cout << endl;

initiaizer_list

都用第一种,不会用第二种的

// 1
map<string, string> dict = { {"left", "左边"}, {"right", "右边"}, {"insert", "插入"},{ "string", "字符串" } };
// 2
pair<string, string> kv1("string", "一");
map<string, string> dict = { kv1, pair<string, string>("一", "二") };

用最外层括号给给initiaizer_list,里面的{}隐式类型转换为pair的两个参数
在这里插入图片描述

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

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

相关文章

初始SpringBoot:详解特性和结构

??JAVA码农探花&#xff1a; ?? 推荐专栏&#xff1a;《SSM笔记》《SpringBoot笔记》 ??学无止境&#xff0c;不骄不躁&#xff0c;知行合一 目录 前言 一、SpringBoot项目结构 1.启动类的位置 2.pom文件 start parent 打包 二、依赖管理特性 三、自动配置特性…

服务器日志自动上传到阿里云OSS备份

背景 公司服务器磁盘空间有限&#xff0c;只能存近15天日志&#xff0c;但是有时需要查看几个月前的日志&#xff0c;需要将服务器日志定时备份到某个地方&#xff0c;需要查询的时候有地方可查。 针对这个问题&#xff0c;想到3个解决方法&#xff1a; 1、买一个配置比较低…

【HarmonyOS NEXT】华为分享-碰一碰开发分享

关键词&#xff1a;鸿蒙、碰一碰、systemShare、harmonyShare、Share Kit 华为分享新推出碰一碰分享&#xff0c;支持用户通过手机碰一碰发起跨端分享&#xff0c;可实现传输图片、共享wifi等。我们只需调用系统 api 传入所需参数拉起对应分享卡片模板即可&#xff0c;无需对 U…

C语言——文件操作

目录 前言 一什么是文件 1程序文件 2数据文件 3文件名 二文件的打开与关闭 1文件指针 2fopen 3fclose 三文件的读与写 1文件的顺序读写 1.1fputc fgetc 1.2fputs fgets 1.3fprintf fscanf 1.4fwrite fread 1.5文本文件和二进制文件 2文件的任意读写 1fseek …

亚博microros小车-原生ubuntu支持系列:1 键盘控制

背景&#xff1a;电脑配置不太行&#xff0c;我在ubuntu再运行vmware&#xff0c;里面运行亚博官方的虚拟机镜像ubuntu&#xff0c;系统很卡。基本上8G内存给打满了。还是想把亚博官方的代码迁移出来&#xff0c;之前售后就说除了官方镜像虚拟机&#xff0c;需要自己摸索迁移。…

基于Redis实现短信验证码登录

目录 1 基于Session实现短信验证码登录 2 配置登录拦截器 3 配置完拦截器还需将自定义拦截器添加到SpringMVC的拦截器列表中 才能生效 4 Session集群共享问题 5 基于Redis实现短信验证码登录 6 Hash 结构与 String 结构类型的比较 7 Redis替代Session需要考虑的问题 8 …

Golang Gin系列-4:Gin Framework入门教程

在本章中&#xff0c;我们将深入研究Gin&#xff0c;一个强大的Go语言web框架。我们将揭示制作一个简单的Gin应用程序的过程&#xff0c;揭示处理路由和请求的复杂性。此外&#xff0c;我们将探索基本中间件的实现&#xff0c;揭示精确定义路由和路由参数的技术。此外&#xff…

Asp.Net Core 8.0 使用 Serilog 按日志级别写入日志文件的两种方式

1、所需的Nuget包 本文项目的版本是.NET 8.0&#xff0c;如果使用其它版本安装适配版本即可。 Serilog.AspNetCore(8.0.2) Serilog.Sinks.File(5.0.0) Serilog.Expressions(5.0.0) 2、两种配置方式 2.1 代码形式&#xff08;Program.cs&#xff09; 在Program.cs文件中&am…

STM32+W5500+以太网应用开发+003_TCP服务器添加OLED(u8g2)显示状态

STM32W5500以太网应用开发003_TCP服务器添加OLED&#xff08;u8g2&#xff09;显示状态 实验效果3-TCP服务器OLED1 拷贝显示驱动代码1.1 拷贝源代码1.2 将源代码添加到工程1.3 修改代码优化等级1.4 添加头文件路径1.5 修改STM32CubeMX工程 2 修改源代码2.1 添加头文件2.2 main函…

【深度学习项目】语义分割-DeepLab网络(DeepLabV3介绍、基于Pytorch实现DeepLabV3网络)

文章目录 介绍深度学习语义分割的关键特点主要架构和技术数据集和评价指标总结 DeepLabDeepLab 的核心技术DeepLab 的发展历史DeepLab V3网络结构获取多尺度信息架构Cascade ModelASPP ModelMulti-GridPytorch官方实现的DeepLab V3该项目主要是来自pytorch官方torchvision模块中…

Golang Gin系列-5:数据模型和数据库

在这篇Gin教程的博客中&#xff0c;我们将探索如何将模型和数据库与Gin框架无缝集成&#xff0c;使你能够构建健壮且可扩展的web应用程序。通过利用流行的库并遵循最佳实践&#xff0c;你将学习如何定义模型、建立数据库连接、执行CRUD操作以及确保基于gin的项目中的数据完整性…

高并发内存池_各层级的框架设计及ThreadCache(线程缓存)申请内存设计

一、高并发内存池框架设计 高并发池框架设计&#xff0c;特别是针对内存池的设计&#xff0c;需要充分考虑多线程环境下&#xff1a; 性能问题锁竞争问题内存碎片问题 高并发内存池的整体框架设计旨在提高内存的申请和释放效率&#xff0c;减少锁竞争和内存碎片。 高并发内存…

如何在idea中搭建SpringBoot项目

如何在idea中快速搭建SpringBoot项目 目录 如何在idea中快速搭建SpringBoot项目前言一、环境准备&#xff1a;搭建前的精心布局 1.下载jdk &#xff08;1&#xff09;安装JDK&#xff1a;&#xff08;2&#xff09;运行安装程序&#xff1a;&#xff08;3&#xff09;设置安装…

elementUI Table组件实现表头吸顶效果

需求描述 当 table 内容过多的时候&#xff0c;页面上滑滚动&#xff0c;表头的信息也会随着被遮挡&#xff0c;无法将表头信息和表格内容对应起来&#xff0c;需要进行表头吸顶 开始编码&#x1f4aa; 环境&#xff1a;vue2.6、element UI step1&#xff1a; 给el-table__h…

[Qt]系统相关-多线程、线程安全问题以及线程的同步机制

目录 一、Qt多线程编程 1.介绍 2.多线程的操作 线程的创建 QThread的常用API 使用案例 3.Qt线程的使用场景 二、线程安全问题 1.互斥锁 介绍 使用案例 2.读写锁 三、线程的同步 1.条件变量 2.信号量 一、Qt多线程编程 1.介绍 Qt中的多线程的底层原理和注意事项…

Linux Bash 中使用重定向运算符的 5 种方法

注&#xff1a;机翻&#xff0c;未校。 Five ways to use redirect operators in Bash Posted: January 22, 2021 | by Damon Garn Redirect operators are a basic but essential part of working at the Bash command line. See how to safely redirect input and output t…

【Linux】环境变量

&#x1f525;个人主页&#x1f525;&#xff1a;孤寂大仙V &#x1f308;收录专栏&#x1f308;&#xff1a;Linux &#x1f339;往期回顾&#x1f339;&#xff1a;【Linux】进程优先级与进程切换 &#x1f516;流水不争&#xff0c;争的是滔滔不 一、环境变量的定义二、命令…

Spring MVC:设置响应

目录 引言 1. 返回静态页面 1.1 Spring 默认扫描路径 1.2 RestController 1.2.1 Controller > 返回页面 1.2.2 ResponseBody 2. 返回 HTML 2.1 RequestMapping 2.1.1 produces(修改响应的 Content-Type) 2.1.2 其他属性 3. 返回 JSON 4. 设置状态码 4.1 HttpSer…

开篇:吴恩达《机器学习》课程及免费旁听方法

课程地址&#xff1a; Machine Learning | Coursera 共包含三个子课程 Supervised Machine Learning: Regression and Classification | Coursera Advanced Learning Algorithms | Coursera Unsupervised Learning, Recommenders, Reinforcement Learning | Coursera 免费…

【C++】模板(进阶)

本篇我们来介绍更多关于C模板的知识。模板初阶移步至&#xff1a;【C】模板&#xff08;初阶&#xff09; 1.非类型模板参数 1.1 非类型模板参数介绍 模板参数可以是类型形参&#xff0c;也可以是非类型形参。类型形参就是我们目前接触到的一些模板参数。 //类型模板参数 …