map和set的使用(一)详解

news2025/1/22 5:01:27

文章目录

  • 序列式容器和关联式容器
  • 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 


	// 返回 >= 25
	auto lowit = myset.lower_bound(25);
	// 返回 > 55
	auto 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;
            else
            p.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++11
    dict.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.coloradmin.cn/o/2280161.html

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

相关文章

CSS布局与响应式

学习链接 Grid网格布局 前端五大主流网页布局 flex布局看这一篇就够了 grid布局看这一篇就够了 用六个案例学会响应式布局 伸缩盒响应式页面布局实战 实现响应式布局的五种方式 - csdn 如何完成响应式布局&#xff0c;有几种方法&#xff1f;看这个就够了 响应式布局总…

P6周:VGG-16算法-Pytorch实现人脸识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 我的环境 语言环境&#xff1a;Python 3.8.12 编译器&#xff1a;jupyter notebook 深度学习环境&#xff1a;torch 1.12.0cu113 一、前期准备 1.设置GPU im…

Git:问题解决办法 及 Tips 总结

目录 查看历史记录及比较区别查看所有提交的历史记录查看提交的详细历史记录查看提交之间的差异点击文件操作历史&#xff0c;筛选出所有改动过此文件的提交任意两个提交之间的比较&#xff08;开发及查BUG常用&#xff09; 在需要版本回滚的情况下处理方法短时间内无法彻查BUG…

【优选算法】----移动零

好久没写博客的兄弟姐妹们~ 今天来写一篇算法过过水吧~ --------------------------------------begin---------------------------------------- 题目要求&#xff1a; 给的难度是简单哦 题目解析&#xff1a; 这道题的思路可以借助双指针的思想&#xff0c;定义dest和c…

Solana 套利机器人原理

引言 加密货币的交易世界中&#xff0c;套利是利用市场价格差异进行无风险获利的一种策略。随着 DeFi&#xff08;去中心化金融&#xff09;的快速发展&#xff0c;套利机会屡见不鲜&#xff0c;尤其是在高速、高效能的区块链上&#xff0c;如 Solana。这些区块链通过提供低交易…

springboot自动配置原理(高低版本比较)spring.factories文件的作用

SpringBootApplication public class SpringSecurityApplication {public static void main(String[] args) {SpringApplication.run(SpringSecurityApplication.class, args);}}注解SpringBootApplication Target({ElementType.TYPE}) Retention(RetentionPolicy.RUNTIME) Doc…

总结4..

#include <stdio.h> // 定义全局变量n&#xff0c;用于表示二维数组的大小 // 定义二维数组b&#xff0c;用于标记找到单词的位置&#xff0c;初始化为0 int n, b[200][200] {0}; // 定义二维数组d&#xff0c;存储8个方向的偏移量&#xff0c;用于在二维数组中搜索…

从零开始:Spring Boot核心概念与架构解析

引言 在当今的Java开发领域&#xff0c;Spring Boot已经成为构建企业级应用的首选框架之一。它以其简洁、高效、易于上手的特点&#xff0c;极大地简化了Spring应用的开发过程。本文将从Spring Boot的核心概念入手&#xff0c;深入解析其架构设计和运行原理&#xff0c;帮助读…

深入 Flutter 和 Compose 的 PlatformView 实现对比,它们是如何接入平台控件

在上一篇《深入 Flutter 和 Compose 在 UI 渲染刷新时 Diff 实现对比》发布之后&#xff0c;收到了大佬的“催稿”&#xff0c;想了解下 Flutter 和 Compose 在 PlatformView 实现上的对比&#xff0c;恰好过去写过不少 Flutter 上对于 PlatformView 的实现&#xff0c;这次恰好…

无人机飞手考证难度增加,实操、地面站教学技术详解

随着无人机技术的快速发展和广泛应用&#xff0c;无人机飞手考证的难度确实在不断增加。这主要体现在对飞手的实操技能和地面站操作技术的要求上。以下是对无人机飞手考证中实操和地面站教学技术的详细解析&#xff1a; 一、实操教学技术详解 1. 无人机基础知识学习&#xff1…

linux下springboot项目nohup日志或tomcat日志切割处理方案

目录 1. 配置流程 2. 配置说明 其他配置选项&#xff1a; 3. 测试执行 4. 手动执行 https://juejin.cn/post/7081890486453010469 通常情况下&#xff0c;我们的springboot项目部署到linux服务器中&#xff0c;通过nohup java -jar xxx.jar &指令来进行后台运行我们…

知识图谱可视化:揭示隐藏的模式与关系

目录 前言1. 什么是知识图谱可视化1.1 知识图谱概述1.2 知识图谱可视化的定义 2. 知识图谱可视化的意义2.1 降低理解门槛2.2 帮助发现模式与洞察2.3 提升交互性与用户体验 3. 知识图谱可视化的技术实现3.1 数据处理与准备3.2 可视化技术3.3 用户交互设计 4. 知识图谱可视化的应…

深度学习基础--LSTM学习笔记(李沐《动手学习深度学习》)

前言 LSTM是RNN模型的升级版&#xff0c;神经网络模型较为复杂&#xff0c;这里是学习笔记的记录&#xff1b;LSTM比较复杂&#xff0c;可以先看&#xff1a; 深度学习基础–一文搞懂RNN 深度学习基础–GRU学习笔记(李沐《动手学习深度学习》) RNN&#xff1a;RNN讲解参考&am…

电气防火保护器为高校学生宿舍提供安全保障

摘 要&#xff1a;3月2日&#xff0c;清华大学紫荆学生公寓发生火情&#xff0c;无人员伤亡。推断起火原因系中厅内通电电器发生故障引燃周边可燃物所致。2月27日&#xff0c;贵州某高校女生宿舍发生火灾&#xff0c;现场明火得到有效控制&#xff0c;无人员受伤。2月19日&…

每打开一个chrome页面都会【自动打开F12开发者模式】,原因是 使用HBuilderX会影响谷歌浏览器的浏览模式

打开 HBuilderX&#xff0c;点击 运行 -> 运行到浏览器 -> 设置web服务器 -> 添加chrome浏览器安装路径 chrome谷歌浏览器插件 B站视频下载助手插件&#xff1a; 参考地址&#xff1a;Chrome插件 - B站下载助手&#xff08;轻松下载bilibili哔哩哔哩视频&#xff09…

C#使用WMI获取控制面板中安装的所有程序列表

C#使用WMI获取控制面板中安装的所有程序列表 WMI 全称Windows Management Instrumentation,Windows Management Instrumentation是Windows中用于提供共同的界面和对象模式以便访问有关操作系统、设备、应用程序和服务的管理信息。如果此服务被终止&#xff0c;多数基于 Windo…

企业级流程架构设计思路-基于价值链的流程架构

获取更多企业流程资料 纸上得来终觉浅&#xff0c;绝知此事要躬行 一.企业流程分级规则定义 1.流程分类分级的总体原则 2.完整的流程体系需要体现出流程的分类分级 03.通用的流程分级方法 04.流程分级的标准 二.企业流程架构设计原则 1.流程架构设计原则 流程框架是流程体…

PyTorch使用教程(8)-一文了解torchvision

一、什么是torchvision torchvision提供了丰富的功能&#xff0c;主要包括数据集、模型、转换工具和实用方法四大模块。数据集模块内置了多种广泛使用的图像和视频数据集&#xff0c;如ImageNet、CIFAR-10、MNIST等&#xff0c;方便开发者进行训练和评估。模型模块封装了大量经…

如何将自己本地项目开源到github上?

环境&#xff1a; LLMB项目 问题描述&#xff1a; 如何将自己本地项目开源到github上&#xff1f; 解决方案&#xff1a; 步骤 1: 准备本地项目 确保项目整洁 确认所有的文件都在合适的位置&#xff0c;并且项目的 README.md 文件已经完善。检查是否有敏感信息&#xff0…

ConvBERT:通过基于跨度的动态卷积改进BERT

摘要 像BERT及其变体这样的预训练语言模型最近在各种自然语言理解任务中取得了令人印象深刻的性能。然而&#xff0c;BERT严重依赖于全局自注意力机制&#xff0c;因此存在较大的内存占用和计算成本。尽管所有的注意力头都从全局角度查询整个输入序列以生成注意力图&#xff0…