map和set的具体用法 【C++】

文章目录

  • 关联式容器
  • 键值对
  • set
    • set的定义方式
      • set的使用
  • multiset
  • map
    • map的定义方式
      • insert
      • find
      • erase
      • []运算符重载
      • map的迭代器遍历
  • multimap

关联式容器

关联式容器里面存储的是<key, value>结构的键值对,在数据检索时比序列式容器效率更高。比如:set、map、unordered_set、unordered_map等

注意: C++STL当中的stack、queue和priority_queue属于容器适配器,它们默认使用的基础容器分别是deque、deque和vector

键值对

键值对是用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息。

比如:建立一个英译汉的字典,那么该字典中的英文单词与其对应的中文含义就是一一对应的关系,即通过单词可以找到与其对应的中文含义。

在SGI-STL中关于键值对的定义如下:

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

1、set是按照一定次序存储元素的容器,使用set的迭代器遍历set中的元素,可以得到有序序列

2、set当中存储元素的value都是唯一的,不可以重复,因此可以使用set进行去重

3、与map/multimap不同,map/multimap中存储的是真正的键值对<key, value>,set中只放value,但在底层实际存放的是由<value, value>构成的键值对,在set容器中插入元素时,只需要插入value即可,不需要构造键值对

4、set中的元素不能被修改,set在底层是用二叉搜索树来实现的,若是对二叉搜索树当中某个结点的值进行了修改,那么这棵树将不再是二叉搜索树

5、在内部,set中的元素总是按照其内部比较对象所指示的特定严格弱排序准则进行排序。当不传入内部比较对象时,set中的元素默认按照小于来比较

6、set容器通过key访问单个元素的速度通常比unordered_set容器慢,但set容器允许根据顺序对元素进行直接迭代

7、set在底层是用平衡搜索树(红黑树)实现的,所以在set当中查找某个元素的时间复杂度为logN

set的定义方式

//构造int类型的空容器
set<int> s1; //拷贝构造int类型s1
set<int> s2(s1); 
string str("abcdef");//拷贝string
set<char> s3(str.begin(), str.end()); //构造int类型的空容器,比较方式指定为大于
set < int, greater<int>> s4; 

set的使用

void Testset()
{//去重set<int> s;s.insert(1);s.insert(4);s.insert(3);s.insert(3);s.insert(2);s.insert(2);s.insert(3);//遍历方式一for (auto e : s){cout << e << " ";}cout << endl;//删除方式一s.erase(3);//遍历方式二set<int>::iterator it = s.begin();while (it != s.end()){cout << *it << " ";it++;}cout << endl;//删除方式二, 正向迭代器遍历 set<int>::iterator pos = s.find(1);if (pos!=s.end()){s.erase(pos);}//遍历方式三set<int>::reverse_iterator rit = s.rbegin();while (rit != s.rend()){cout << *rit << " ";rit++;}cout << endl;//容器中值为2的个数 cout<<s.count(2);cout << s.size();s.clear();cout << s.empty();}void TestmultiSet()
{//可以重复 multiset<int> m;m.insert(3);m.insert(5);m.insert(8);m.insert(7);m.insert(7);m.insert(9);m.insert(7);for (auto e : m){cout << e << "";}//find //set<int> s;//s.insert(1);//s.insert(4);//s.insert(3);//s.insert(3);//s.insert(2);//s.insert(2);//s.insert(3);//if (s.find(3) != s.end())//{//	cout << "找到了" << " ";//}//else//{//	cout << "找不到" << " ";//}auto pos = m.find(7);//返回中序中第一个7while (pos != m.end()){cout << *pos << " ";pos++;}cout << endl;cout << m.count(7) << endl;auto ret = m.equal_range(17);auto itlow = ret.first;auto itup = ret.second;//[itlow , itup) 左闭右开 左边界是第一个7,右边界是比7大的,才能完全删除所有的7cout << *itlow<<endl;cout << *itup<<endl;m.erase(itlow, itup);//?for (auto e : m){cout << e << " ";}cout << endl;}
void Testset2()
{set<int> s;s.insert(1);s.insert(4);s.insert(3);s.insert(3);s.insert(2);s.insert(2);s.insert(3);//交换两个容器的数据 set<int> tmp{ 11,22,33,44 };s.swap(tmp);for (auto e : s){cout << e << " ";}cout << endl;
}int main()
{
Testset();
TestmultiSet();
Testset2();
return 0 ;
}

multiset

multiset容器与set容器的底层实现一样,都是平衡搜索树(红黑树),其次,multiset容器和set容器所提供的成员函数的接口都是基本一致的,multiset容器和set容器的唯一区别就是,multiset允许键值冗余,即multiset容器当中存储的元素是可以重复的。

#include <iostream>
#include <set>
using namespace std;int main()
{multiset<int> ms;//插入元素(允许重复)ms.insert(1);ms.insert(4);ms.insert(3);ms.insert(3);ms.insert(2);ms.insert(2);ms.insert(3);for (auto e : ms){cout << e << " ";}cout << endl; //1 2 2 3 3 3 4return 0;
}

在这里插入图片描述

map

1、map是关联式容器,它按照特定的次序(按照key来比较)存储键值key和值value组成的元素,使用map的迭代器遍历map中的元素,可以得到有序序列。

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

3、map容器中元素的键值key不能被修改,但是元素的值value可以被修改,因为map底层的二叉搜索树是根据每个元素的键值key进行构建的,而不是值value。

4、在内部,map中的元素总是按照键值key进行比较排序的。当不传入内部比较对象时,map中元素的键值key默认按照小于来比较。

5、map容器通过键值key访问单个元素的速度通常比unordered_map容器慢,但map容器允许根据顺序对元素进行直接迭代。

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

7、map在底层是用平衡搜索树(红黑树)实现的,所以在map当中查找某个元素的时间复杂度为logN

map的定义方式

map<int, double> m1; //构造一个key为int类型,value为double类型的空容器map<int, double> m2(m1); //拷贝构造key为int类型,value为double类型的m1容器的复制品map<int, double> m3(m2.begin(), m2.end()); //使用迭代器拷贝构造m2容器某段区间的复制品map<int, double, greater<int>> m4; //构造一个key为int类型,value为double类型的空容器,key比较方式指定为大于

insert

在这里插入图片描述

pair<iterator,bool> insert (const value_type& val);

value_type类型的,实际上value_type就是pair类型的别名:

typedef pair<const Key, T> value_type;

插入元素时,需要用key和value构造一个pair对象,然后再将pair对象作为参数传入insert函数

方式一:匿名对象

#include <iostream>
#include <string>
#include <map>
using namespace std;int main()
{map<int, string> m;//方式一:调用pair的构造函数,构造一个匿名对象插入m.insert(pair<int, string>(2, "two"));m.insert(pair<int, string>(1, "one"));m.insert(pair<int, string>(3, "three"));for (auto e : m){cout << "<" << e.first << "," << e.second << ">" << " ";}cout << endl; //<1,one> <2,two> <3,three>return 0;
}

方式二:调用make_pair函数模板插入(常用)

库当中提供以下make_pair函数模板:

template <class T1, class T2>
pair<T1, T2> make_pair(T1 x, T2 y)
{return (pair<T1, T2>(x, y));
}

向make_pair函数传入key和value,该函数模板会根据传入参数类型进行自动隐式推导,最终构造并返回一个对应的pair对象

#include <iostream>
#include <string>
#include <map>
using namespace std;int main()
{map<int, string> m;//方式二:调用函数模板make_pair,构造对象插入m.insert(make_pair(2, "two"));m.insert(make_pair(1, "one"));m.insert(make_pair(3, "three"));for (auto e : m){cout << "<" << e.first << "," << e.second << ">" << " ";}cout << endl; //<1,one> <2,two> <3,three>return 0;
}

insert函数的返回值
在这里插入图片描述
总结文档的内容:
insert函数的返回值也是一个pair对象,该pair对象中第一个成员的类型是map的迭代器类型,第二个成员的类型的一个bool类型,具体含义如下:

1、如果待插入元素的键值key在map当中不存在,则insert函数插入成功,并返回插入后元素的迭代器和true。
2、如果待插入元素的键值key在map当中已经存在,则insert函数插入失败,并返回map当中键值为key的元素的迭代器和false。

find

在这里插入图片描述

iterator find (const key_type& k);

根据所给key值在map当中进行查找,若找到了,则返回对应元素的迭代器,若未找到,则返回容器中最后一个元素下一个位置的正向迭代器。

#include <iostream>
#include <string>
#include <map>
using namespace std;int main()
{map<int, string> m;m.insert(make_pair(2, "two"));m.insert(make_pair(1, "one"));m.insert(make_pair(3, "three"));//获取key值为2的元素的迭代器map<int, string>::iterator pos = m.find(2);if (pos != m.end()){cout << pos->second << endl; //two}return 0;
}

erase

在这里插入图片描述
根据key值删除指定元素,也可以根据迭代器删除指定元素,若是根据key值进行删除,则返回实际删除的元素个数。

#include <iostream>
#include <string>
#include <map>
using namespace std;int main()
{map<int, string> m;m.insert(make_pair(2, "two"));m.insert(make_pair(1, "one"));m.insert(make_pair(3, "three"));for (auto kv : m){cout << kv.first<<" " << kv.second;}cout << endl;//根据key值进行删除m.erase(3);for ( auto kv : m){cout << kv.first << " " << kv.second;}//根据迭代器删除 map<int, string>::iterator pos = m.find(2);while (pos != m.end()){m.erase(pos);}for (auto kv : m){cout << kv.first << " " << kv.second;}return 0;
}

[]运算符重载

在这里插入图片描述
在这里插入图片描述
[ ]运算符重载函数的参数就是一个key值,而这个函数的返回值如下:

(* (  (this->insert(  make_pair(k, mapped_type() ) ) ).first)   ).second

根据上述代码可以推断出[ ],运算符重载实现的逻辑:

mapped_type& operator[] (const key_type& k)
{//1、调用insert函数插入键值对pair<iterator, bool> ret = insert( make_pair(k, mapped_type() ) );//2、拿出从insert函数获取到的迭代器iterator it = ret.first;//3、返回该迭代器位置元素的值valuereturn it->second;
}

[]运算符的使用

int main()
{map<string, string> dict;dict.insert(make_pair("string", "字符串"));dict.insert(make_pair("sort", "排序"));dict.insert(make_pair("insert", "插入"));cout << dict["sort"] << endl;//查找和读dict["map"];//插入dict["map"] = "映射,地图";//修改dict["insert"] = "xxx";//修改dict["set"] = "集合";//插入+修改
}

总结一下:
1、如果k不在map中,则先插入键值对<k, V()>,然后返回该键值对中V对象的引用。
2、如果k已经在map中,则返回键值为k的元素对应的V对象的引用。

map的迭代器遍历

int main()
{map<int, string>  m;m.insert(make_pair(2, "two"));m.insert(make_pair(1, "one"));m.insert(make_pair(3, "three"));//正向迭代器 map<int, string>::iterator   it = m.begin();while (it != m.end()){//cout << (*it).first << ":"<<(*it).second<<endl;//迭代器重载operator*cout << it->first << ":" << it->second << endl;//迭代器重载operator->it++;	}cout << endl;//反向迭代器 map<int, string>::reverse_iterator rit = m.rbegin();while (rit != m.rend()){cout << " " << rit->first << " " << rit->second;rit++;}cout << endl;//范围for ,kv就是*itfor (auto kv : m){cout << kv.first <<" " << kv.second;}return 0;
}

multimap

multimap容器与map容器的底层实现一样,也都是平衡搜索树(红黑树),multimap容器和map容器的区别与multiset容器和set容器的区别一样,multimap允许键值冗余,即multimap容器当中存储的元素是可以重复的。

#include <iostream>
#include <string>
#include <map>
using namespace std;int main()
{multimap<int, string> mm;//插入元素(允许重复)mm.insert(make_pair(2, "two"));mm.insert(make_pair(2, "double"));mm.insert(make_pair(1, "one"));mm.insert(make_pair(3, "three"));for (auto e : mm){cout << "<" << e.first << "," << e.second << ">" << " ";}cout << endl; //<1,one> <2,two> <2,double> <3,three>return 0;
}

在这里插入图片描述
如果你觉得这篇文章对你有帮助,不妨动动手指给点赞收藏加转发,给鄃鳕一个大大的关注
你们的每一次支持都将转化为我前进的动力!!

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

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

相关文章

ARP欺骗攻击实操

目录 目录 前言 系列文章列表 全文导图 1&#xff0c;ARP概述 1.1,ARP是什么&#xff1f; 1.2,ARP协议的基本功能 1.3,ARP缓存表 1.4,ARP常用命令 2&#xff0c;ARP欺骗 2.1,ARP欺骗的概述? 2.2,ARP欺骗的攻击手法 3&#xff0c;ARP攻击 3.1,攻击前的准备 3.2,…

【Spring Boot】实战:实现数据缓存框架

🌿欢迎来到@衍生星球的CSDN博文🌿 🍁本文主要学习【Spring Boot】实现数据缓存框架 🍁 🌱我是衍生星球,一个从事集成开发的打工人🌱 ⭐️喜欢的朋友可以关注一下🫰🫰🫰,下次更新不迷路⭐️💠作为一名热衷于分享知识的程序员,我乐于在CSDN上与广大开发者…

Python3 如何实现 websocket 服务?

Python 实现 websocket 服务很简单&#xff0c;有很多的三方包可以用&#xff0c;我从网上大概找到三种常用的包&#xff1a;websocket、websockets、Flask-Sockets。 但这些包很多都“年久失修”&#xff0c; 比如 websocket 在 2010 年就不维护了。 而 Flask-Sockets 也在 2…

SQL血缘解析原理

根据sql解析获取到表到表, 字段到字段间的关系,即血缘关系。实际上这是从sql文本获取到数据流的过程。 大致步骤如下&#xff1a; 1.sql文本进行词法分析 2.sql语法分析获取到AST抽象语法树 3.访问AST抽象语法树根据语法结构推测出数据的流向,例如create as select from 这种结…

[vue-admin-template实战笔记]

1.克隆项目 git clone gitgitee.com:panjiachen/vue-admin-template.git 2.安装依赖 npm install 3.运行项目就会自动打开网页&#xff0c;并且热部署插件 npm run dev 4.查看代码 //将vue-admin-template拖入到idea中即可查看代码 1)并且发现&#xff0c;常用的东西已经集…

Machine Learning(study notes)

There is no studying without going crazy Studying alwats drives us crazy 文章目录 DefineMachine LearningSupervised Learning&#xff08;监督学习&#xff09;Regression problemClassidication Unspervised LearningClustering StudyModel representation&#xff08…

unity 鼠标标记 左键长按生成标记右键长按清除标记,对象转化为子物体

linerender的标记参考 unity linerenderer在Game窗口中任意画线_游戏内编辑linerender-CSDN博客 让生成的标记转化为ARMarks游戏对象的子物体 LineMark.cs using System.Collections; using System.Collections.Generic; using UnityEngine;public class LineMark : MonoBeh…

excel筛选后求和

需要对excel先筛选&#xff0c;后对“完成数量”进行求和。初始表格如下&#xff1a; 一、选中表内任意单元格&#xff0c;按ctrlshiftL&#xff0c;开启筛选 二、根据“部门”筛选&#xff0c;比如选择“一班” 筛选完毕后&#xff0c;选中上图单元格&#xff0c;然后按alt后&…

JavaScript Web APIs第一天笔记

复习&#xff1a; splice() 方法用于添加或删除数组中的元素。 **注意&#xff1a;**这种方法会改变原始数组。 删除数组&#xff1a; splice(起始位置&#xff0c; 删除的个数) 比如&#xff1a;1 let arr [red, green, blue] arr.splice(1,1) // 删除green元素 consol…

Unity如何生成随机数(设置种子)

文章目录 随机类整数二维向量三维向量种子其他文章 随机类 我们可以使用Random类来生成一些随机数 Random类是用于生成随机数的类之一。它可以用于生成不同类型的随机数&#xff0c;如整数、浮点数和向量。 整数 我们可以使用Random.Range来生成指定范围内的随机整数或浮点数…

Windows 安装CMake

CMake 简介 CMake是一个开源的、跨平台的自动化构建系統&#xff0c;用來管理软件构建的过程。 其用途主要包括&#xff1a; 1. 跨平台编译&#xff1a;CMake支援Windows&#xff0c;Mac OS&#xff0c;Linux等多种操作系統&#xff0c;且支援多数主流编译器如GCC&#xff0…

智能合约漏洞,Dyna 事件分析

智能合约漏洞&#xff0c;Dyna 事件分析 1. 漏洞简介 https://twitter.com/BlockSecTeam/status/1628319536117153794 https://twitter.com/BeosinAlert/status/1628301635834486784 2. 相关地址或交易 攻击交易 1&#xff1a; https://bscscan.com/tx/0x7fa89d869fd1b89e…

【STL巨头】set、map、multiset、multimap的介绍及使用

set、map、multiset、multimap的介绍及使用 一、关联式容器二、键值对键值对概念定义 三、setset的介绍set的使用set的模板参数列表set的构造set的迭代器set的容量emptysize set的修改操作insertfind && erasecountlower_bound 和 upper_bound Multiset的用法 四、mapm…

inndy_echo

inndy_echo Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)32位&#xff0c;只开了NX int __cdecl __noreturn main(int argc, const char **argv, const char **envp) {char s; // [espCh…

Unity2023打包首包从78Mb到3.0Mb-震惊-我做对了什么

&#xff08;全程并没有使用AssetBundle , 历史原因&#xff0c;Resources目录还有不少资源残留&#xff09; 曾经的我在2019打包过最小包10m左右&#xff0c;后来发现到了Unity2020之后暴增到40m&#xff0c;又加上2023版本URP&#xff0c;1个Unity输出包可能至少55M 如下图…

华为智能高校出口安全解决方案(3)

本文承接&#xff1a; https://qiuhualin.blog.csdn.net/article/details/133267254?spm1001.2014.3001.5502 重点讲解华为智能高校出口安全解决方案的攻击防御&安全运维&日志审计的部署流程。 华为智能高校出口安全解决方案&#xff08;3&#xff09; 课程地址攻击防…

基于Vue+ELement实现增删改查案例与表单验证(附源码)

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《ELement》。&#x1f3af;&#x1f3af; &#x1…

孤举者难起,众行者易趋,openGauss 5.1.0版本正式发布!

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

Java获取给定月份的前N个月份和前N个季度

描述&#xff1a; 在项目开发过程中&#xff0c;遇到这样一个需求&#xff0c;即&#xff1a;给定某一月份&#xff0c;得到该月份前面的几个月份以及前面的几个季度。例如&#xff1a;给定2023-09&#xff0c;获取该月份前面的前3个月&#xff0c;即2023-08、2023-07、2023-0…

基于微信小程的流浪动物领养小程序设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言系统主要功能&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计…