C++STL容器——map和set

目录

一.关联式容器

二.键值对

三.树形结构的关联式容器

1.set

2.map

3.multiset和multimap

四.整体代码

map_set.cpp


一.关联式容器

在初阶阶段,我们已经接触过STL中的部分容器,比如:vector、list、deque、 forward_list(C++11)等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身。那什么是关联式容器?它与序列式容器有什么区别?

关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是结构的键值对,在数据检索时比序列式容器效率更高

二.键值对

用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量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)
{}
};

三.树形结构的关联式容器

根据应用场景的不桶,STL总共实现了两种不同结构的管理式容器:树型结构与哈希结构。树型结 构的关联式容器主要有四种:map、set、multimap、multiset。这四种容器的共同点是:使用平衡搜索树(即红黑树)作为其底层结果容器中的元素是一个有序的序列

1.set

set文档介绍

  1. set是按照一定次序存储元素的容器
  2. 在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的
  3. 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行 排序
  4. set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对子集进行直接迭代
  5. set在底层是用二叉搜索树(红黑树)实现的

注意:

  1. 与map/multimap不同,map/multimap中存储的是真正的键值对,set中只放value,但在底层实际存放的是由构成的键值对
  2. set中插入元素时,只需要插入value即可,不需要构造键值对
  3. set中的元素不可以重复(因此可以使用set进行去重)
  4. 使用set的迭代器遍历set中的元素,可以得到有序序列
  5. set中的元素默认按照小于来比较
  6. set中查找某个元素,时间复杂度为:log2N
  7. set中的元素不允许修改
  8. set中的底层使用二叉搜索树(红黑树)来实现

set的使用

void test_set()
{set<int> s;s.insert(3);s.insert(1);s.insert(4);s.insert(3);s.insert(7);//排序+去重set<int>::iterator it = s.begin();while (it != s.end()){//*it += 1;不允许修改cout << *it << " ";++it;}cout << endl;for (auto ch : s){cout << ch << " ";}cout << endl;set<int> copy(s);for (auto ch : copy){cout << ch << " ";}cout << endl;set<int>::iterator pos = s.find(30);if (pos != s.end()){s.erase(pos);}s.erase(4);s.erase(40);for (auto ch : s){cout << ch << " ";}cout << endl;
}

可以看到重复元素被删除了,需要注意的是find查找时需要判断范围,但是erase不需要,但是其实erase底层逻辑是通过find实现的

2.map

map文档介绍

  1. map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元 素
  2. 在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的 内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型 value_type绑定在一起,为其取别名称为pair: typedef pair value_type;
  3. 在内部,map中的元素总是按照键值key进行比较排序的
  4. map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)
  5. map支持下标访问符,即在[]中放入key,就可以找到与key对应的value
  6. map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))

map的使用

void test_map1()
{map<int, int> m;m.insert(pair<int, int>(1, 1));m.insert(pair<int, int>(3, 3));m.insert(pair<int, int>(2, 2));//pair构造函数,构造一个匿名对象m.insert(make_pair(4, 4));//函数模板构造一个pair对象map<int, int>::iterator it = m.begin();while (it != m.end()){//cout << (*it).first << ":" << (*it).second << endl;cout << it->first << ":" << it->second << endl;++it;}cout << endl;for (auto& e : m){cout << e.first << ":" << e.second << endl;}cout << endl;
}

在插入时需要传入一个pair,也可以使用make_pair

接下来我们来看map统计数据时的一些方法

void test_map2()
{//第一种/*string strs[] = { "西瓜","葡萄", "苹果", "西瓜", "橘子", "西瓜", "葡萄", "西瓜", "苹果", "西瓜", "橘子", "葡萄" };map<string, int> countMap;for (auto& str : strs){map<string, int>::iterator ret = countMap.find(str);if (ret != countMap.end()){ret->second++;}else{countMap.insert(make_pair(str, 1));}}for (auto& e : countMap){cout << e.first << ":" << e.second << endl;}cout << endl;*///第二种//string strs[] = { "西瓜","葡萄", "苹果", "西瓜", "橘子", "西瓜", "葡萄", "西瓜", "苹果", "西瓜", "橘子", "葡萄" };//map<string, int> countMap;//for (auto& str : strs)//{//	//如果水果没在map中,则插入成功//	//如果在则插入失败,通过返回值拿到水果所在的节点迭代器,++次数//	pair<map<string, int>::iterator, bool> ret = countMap.insert(make_pair(str, 1));//	if (ret.second == false)//	{//		ret.first->second++;//	}//}//for (auto& e : countMap)//{//	cout << e.first << ":" << e.second << endl;//}//cout << endl;//第三种string strs[] = { "西瓜","葡萄", "苹果", "西瓜", "橘子", "西瓜", "葡萄", "西瓜", "苹果", "西瓜", "橘子", "葡萄" };map<string, int> countMap;for (auto& str : strs){//如果水果不在map中,则operator[]会插入pair<str,0>,返回映射对象(次数)的引用进行了++//如果水果在map中,则operator[]返回水果对应的映射对象(次数),对它++//一般不会用operator[]查找,因为如果key不在会插入数据countMap[str]++;}countMap["香蕉"];//插入countMap["香蕉"] = 1;//修改cout << countMap["香蕉"] << endl;//查找countMap["哈密瓜"] = 5;//插入+修改for (auto& e : countMap){cout << e.first << ":" << e.second << endl;}cout << endl;
}

3.multiset和multimap

multiset文档说明

multimap文档说明

void test_multi()
{//跟set的区别是允许键值冗余multiset<int> ms;ms.insert(3);ms.insert(2);ms.insert(1);ms.insert(3);ms.insert(5);ms.insert(4);for (auto e : ms){cout << e << " ";}cout << endl;//查找时找到的是第一次出现的auto pos = ms.find(3);cout << *pos << endl; ++pos;cout << *pos << endl; ++pos;cout << *pos << endl; ++pos;//multimap和map的区别和上面一样//multimap没有operator[],因为有多个相同的key时,不知道返回哪个key的value
}

四.整体代码

map_set.cpp

#include<iostream>
#include<set>
#include<map>
#include<string>
using namespace std;void test_set()
{set<int> s;s.insert(3);s.insert(1);s.insert(4);s.insert(3);s.insert(7);//排序+去重set<int>::iterator it = s.begin();while (it != s.end()){//*it += 1;不允许修改cout << *it << " ";++it;}cout << endl;for (auto ch : s){cout << ch << " ";}cout << endl;set<int> copy(s);for (auto ch : copy){cout << ch << " ";}cout << endl;set<int>::iterator pos = s.find(30);if (pos != s.end()){s.erase(pos);}s.erase(4);s.erase(40);for (auto ch : s){cout << ch << " ";}cout << endl;
}void test_map1()
{map<int, int> m;m.insert(pair<int, int>(1, 1));m.insert(pair<int, int>(3, 3));m.insert(pair<int, int>(2, 2));//pair构造函数,构造一个匿名对象m.insert(make_pair(4, 4));//函数模板构造一个pair对象map<int, int>::iterator it = m.begin();while (it != m.end()){//cout << (*it).first << ":" << (*it).second << endl;cout << it->first << ":" << it->second << endl;++it;}cout << endl;for (auto& e : m){cout << e.first << ":" << e.second << endl;}cout << endl;
}void test_map2()
{//第一种/*string strs[] = { "西瓜","葡萄", "苹果", "西瓜", "橘子", "西瓜", "葡萄", "西瓜", "苹果", "西瓜", "橘子", "葡萄" };map<string, int> countMap;for (auto& str : strs){map<string, int>::iterator ret = countMap.find(str);if (ret != countMap.end()){ret->second++;}else{countMap.insert(make_pair(str, 1));}}for (auto& e : countMap){cout << e.first << ":" << e.second << endl;}cout << endl;*///第二种//string strs[] = { "西瓜","葡萄", "苹果", "西瓜", "橘子", "西瓜", "葡萄", "西瓜", "苹果", "西瓜", "橘子", "葡萄" };//map<string, int> countMap;//for (auto& str : strs)//{//	//如果水果没在map中,则插入成功//	//如果在则插入失败,通过返回值拿到水果所在的节点迭代器,++次数//	pair<map<string, int>::iterator, bool> ret = countMap.insert(make_pair(str, 1));//	if (ret.second == false)//	{//		ret.first->second++;//	}//}//for (auto& e : countMap)//{//	cout << e.first << ":" << e.second << endl;//}//cout << endl;//第三种string strs[] = { "西瓜","葡萄", "苹果", "西瓜", "橘子", "西瓜", "葡萄", "西瓜", "苹果", "西瓜", "橘子", "葡萄" };map<string, int> countMap;for (auto& str : strs){//如果水果不在map中,则operator[]会插入pair<str,0>,返回映射对象(次数)的引用进行了++//如果水果在map中,则operator[]返回水果对应的映射对象(次数),对它++//一般不会用operator[]查找,因为如果key不在会插入数据countMap[str]++;}countMap["香蕉"];//插入countMap["香蕉"] = 1;//修改cout << countMap["香蕉"] << endl;//查找countMap["哈密瓜"] = 5;//插入+修改for (auto& e : countMap){cout << e.first << ":" << e.second << endl;}cout << endl;
}void test_multi()
{//跟set的区别是允许键值冗余multiset<int> ms;ms.insert(3);ms.insert(2);ms.insert(1);ms.insert(3);ms.insert(5);ms.insert(4);for (auto e : ms){cout << e << " ";}cout << endl;//查找时找到的是第一次出现的auto pos = ms.find(3);cout << *pos << endl; ++pos;cout << *pos << endl; ++pos;cout << *pos << endl; ++pos;//multimap和map的区别和上面一样//multimap没有operator[],因为有多个相同的key时,不知道返回哪个key的value
}int main()
{//test_set();//test_map1();//test_map2();test_multi();
}

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

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

相关文章

Java 责任链模式 减少 if else 实战案例

一、场景介绍 假设有这么一个朝廷&#xff0c;它有 县-->府-->省-->朝廷&#xff0c;四级行政机构。 这四级行政机构的关系如下表&#xff1a; 1、县-->府-->省-->朝廷&#xff1a;有些地方有完整的四级行政机构。 2、县-->府-->朝廷&#xff1a;直…

Rocky、Almalinux、CentOS、Ubuntu和Debian系统初始化脚本v9版

Rocky、Almalinux、CentOS、Ubuntu和Debian系统初始化脚本 Shell脚本源码地址&#xff1a; Gitee&#xff1a;https://gitee.com/raymond9/shell Github&#xff1a;https://github.com/raymond999999/shell脚本可以去上面的Gitee或Github代码仓库拉取。 支持的功能和系统&am…

EXCEL延迟退休公式

如图&#xff1a; A B为手工输入 C2EOMONTH(A2,B2*12) D2EOMONTH(C2,IF(C2>DATEVALUE("2025-1-1"),INT((DATEDIF(DATEVALUE("2025-1-1"),C2,"m")4)/4),0)) E2EOMONTH(A2,B2*12IF(EOMONTH(A2,B2*12)>DATEVALUE("2025-1-1"),INT(…

ARM架构中断与异常向量表机制解析

往期内容 本专栏往期内容&#xff0c;interrtupr子系统&#xff1a; 深入解析Linux内核中断管理&#xff1a;从IRQ描述符到irq domain的设计与实现Linux内核中IRQ Domain的结构、操作及映射机制详解中断描述符irq_desc成员详解Linux 内核中断描述符 (irq_desc) 的初始化与动态分…

论文翻译 | The Capacity for Moral Self-Correction in Large Language Models

摘要 我们测试了一个假设&#xff0c;即通过人类反馈强化学习&#xff08;RLHF&#xff09;训练的语言模型具有“道德自我纠正”的能力——避免产生有害的输出——如果指示这样做的话。我们在三个不同的实验中发现了支持这一假设的有力证据&#xff0c;每个实验都揭示了道德自…

华为云前台用户可挂载数据盘和系统盘是怎么做到的?

用户可以选择磁盘类型和容量&#xff0c;其后台是管理员对接存储设备 1.管理员如何在后台对接存储设备&#xff08;特指业务存储&#xff09; 1.1FusionSphere CPS&#xff08;Cloud Provisionivice&#xff09;云装配服务 它是first node https://10.200.4.159:8890 对接存…

【Excel】身份证号最后一位“X”怎么计算

大多数人身份证号最后一位都是数字&#xff0c;但有个别号码最后一位却是“X"。 如果你查百度&#xff0c;会得到如下答案&#xff1a; 当最后一位编码是10的时候&#xff0c;因为多出一位&#xff0c;所以就用X替换。 可大多数人不知道的是&#xff0c;这个10是怎么来的…

【常见问题解答】远程桌面无法复制粘贴的解决方法

提示:“奔跑吧邓邓子” 的常见问题专栏聚焦于各类技术领域常见问题的解答。涵盖操作系统(如 CentOS、Linux 等)、开发工具(如 Android Studio)、服务器软件(如 Zabbix、JumpServer、RocketMQ 等)以及远程桌面、代码克隆等多种场景。针对如远程桌面无法复制粘贴、Kuberne…

python解析网页上的json数据落地到EXCEL

安装必要的库 import requests import pandas as pd import os import sys import io import urllib3 import json测试数据 网页上的数据结构如下 {"success": true,"code": "CIFM_0000","encode": null,"message": &quo…

change buffer:到底应该选择普通索引还是唯一索引

文章目录 引言第一章&#xff1a;普通索引和唯一索引在查询逻辑与效率上的对比1.1 查询逻辑分析1.2 查询效率对比 第二章&#xff1a;普通索引和唯一索引在更新逻辑与效率上的对比2.1 更新逻辑分析2.2 更新效率对比 第三章&#xff1a;底层原理详解 - 普通索引和唯一索引的区别…

3D编辑器教程:如何实现3D模型多材质定制效果?

想要实现下图这样的产品DIY定制效果&#xff0c;该如何实现&#xff1f; 可以使用51建模网线上3D编辑器的材质替换功能&#xff0c;为产品3D模型每个部位添加多套材质贴图&#xff0c;从而让3D模型在展示时实现DIY定制效果。 具体操作流程如下&#xff1a; 第1步&#xff1a;上…

git入门环境搭建

git下载 git官网地址&#xff1a;https://git-scm.com/ 如果没有魔法的话&#xff0c;官网这个地址能卡死你 这里给个国内的git镜像链接 git历史版本镜像链接 然后一路next 默认路径 默认勾选就行。 今天就写到这吧&#xff0c;11点多了该睡了&#xff0c;&#xff0c;&#x…

Oracle ADB 导入 BANK_GRAPH 的学习数据

Oracle ADB 导入 BANK_GRAPH 的学习数据 1. 下载数据2. 导入数据运行 setconstraints.sql 1. 下载数据 访问 https://github.com/oracle-quickstart/oci-arch-graph/tree/main/terraform/scripts&#xff0c;下载&#xff0c; bank_accounts.csvbank_txns.csvsetconstraints.…

985研一学习日记 - 2024.11.14

一个人内耗&#xff0c;说明他活在过去&#xff1b;一个人焦虑&#xff0c;说明他活在未来。只有当一个人平静时&#xff0c;他才活在现在。 日常 1、起床6:00 2、健身2h 3、LeetCode刷了题 动态规划概念 如果某一问题有很多重叠子问题&#xff0c;使用动态规划是最有效的…

1.两数之和-力扣(LeetCode)

题目&#xff1a; 解题思路&#xff1a; 在解决这个问题之前&#xff0c;首先要明确两个点&#xff1a; 1、参数returnSize的含义是返回答案的大小&#xff08;数目&#xff09;&#xff0c;由于这里的需求是寻找数组中符合条件的两个数&#xff0c;那么当找到这两个数时&#…

【excel】easy excel如何导出动态列

动态也有多重含义&#xff1a;本文将描述两种动态场景下的解决方案 场景一&#xff1a;例如表头第一列固定为动物&#xff0c;且必定有第二列&#xff0c;第二列的表头可能为猫 也可能为狗&#xff1b;这是列数固定&#xff0c;列名不固定的场景&#xff1b; 场景二&#xff1…

〔 MySQL 〕数据类型

目录 1.数据类型分类 2 数值类型 2.1 tinyint类型 2.2 bit类型 2.3 小数类型 2.3.1 float 2.3.2 decimal 3 字符串类型 3.1 char 3.2 varchar 3.3 char和varchar比较 4 日期和时间类型 5 enum和set mysql表中建立属性列&#xff1a; 列名称&#xff0c;类型在后 n…

LlamaIndex

一、大语言模型开发框架 SDK:Software Development Kit,它是一组软件工具和资源的集合,旨在帮助开发者创建、测试、部署和维护应用程序或软件。 所有开发框架(SDK)的核心价值,都是降低开发、维护成本。 大语言模型开发框架的价值,是让开发者可以更方便地开发基于大语言…

【FFmpeg】FFmpeg 函数简介 ③ ( 编解码相关函数 | FFmpeg 源码地址 | FFmpeg 解码器相关 结构体 和 函数 )

文章目录 一、FFmpeg 解码器简介1、解码流程分析2、FFmpeg 编解码器 本质3、FFmpeg 编解码器 ID 和 名称 二、FFmpeg 解码器相关 结构体 / 函数1、AVFormatContext 结构体2、avcodec_find_decoder 函数 - 根据 ID 查找 解码器3、avcodec_find_decoder_by_name 函数 - 根据 名称…

Linux——GPIO输入输出裸机实验

学习了正点原子Linux环境下的GPIO的输入输出的裸机实验学习&#xff0c;现在进行一下小结&#xff1a; 启动文件start.S的编写 .global _start .global _bss_start _bss_start:.word __bss_start.global _bss_end _bss_end:.word __bss_end_start:/*设置处理器进入SVC模式*/m…