当前位置: 首页 > news >正文

【C++篇】STL的关联容器:map和set(上篇)—— map和set的介绍和使用

文章目录

      • 前言
      • 一、set
        • 1.1 set介绍
        • 1.2 set的使用
          • 1.2.1 count
          • 1.2.2 lower_bound和upper_bound
          • 1.2.3 equal_range
      • 二、map
        • 2.1 map介绍
          • 键值对
        • 2.2 map的使用
          • 2.2.1 插入元素
          • 2.2.2 操作接口
          • 2.2.3 元素访问
      • 结语


前言

在我们学习完了STL的stringvectorlist容器后,你知道它们是哪类容器吗?
它们有个共同特点:通过下标(索引)来访问,因此它们都属于顺序容器
那什么是关联容器呢?
关联容器:通过键(key)来存储和访问元素,在数据检索时顺序容器效率更高。
mapset 是 C++ STL 中两种重要的关联容器,它们都基于红黑树(一种自平衡二叉搜索树)实现。

本文内容标题所示,后续我会讲解它们的底层——AVL树和红黑树,并模拟实现它们。


一、set

1.1 set介绍

set文档介绍
在这里插入图片描述
可以看到,它只有一个键值,是一个K模型(这篇文章末尾有介绍)。

既然set的数据结构是平衡二叉搜索树(通常为红黑树),那么它具有如下基本特性:

  1. 有序性(默认升序)
  2. 唯一性(不允许重复元素)
  3. 高效查找(查找次数为数的高度次,时间复杂度为 O(log n))

还有个特点:set的键值是不可以修改的
迭代器的底层代码赋予了这个特性:
在这里插入图片描述

set的本质功能:排序+去重

1.2 set的使用

set的大多数接口是和list类似的,包括迭代器都是类似的,直接平移使用即可,这里我主要讲解它的常用特殊接口,下文map也是如此。

头文件和声明

#include <set>
using namespace std;set<int> mySet;  // 声明一个整型set

在这里插入图片描述

1.2.1 count

在这里插入图片描述

count是什么呢?看后面的介绍似乎是说用一个特殊值统计一个元素的数量。奇怪,元素不是唯一的吗?那数量不是固定就是1吗?哪有什么意义呢?
没错,在set这里确实是没有意义,但set还有个孪生兄弟mutiset,它允许有键值相同的元素出现,这时候统计数量就有意义了。
至于为什么要在set中设计这个接口,我猜可能是为了兼容性。

1.2.2 lower_bound和upper_bound

在这里插入图片描述
功能:返回一个大于等于val的第一个元素的迭代器

在这里插入图片描述
功能:返回一个大于val的第一个元素的迭代器

两者配合起来使用可以确定迭代区间

应用:删除区间元素
在这里插入图片描述

1.2.3 equal_range

在这里插入图片描述
功能:返回元素为val值的迭代器区间

这个接口和count一样,在set中无意义,主要应用在muliset容器。

这里的返回值类型pair是键值对,暂且放一放,后文map我会讲解。


二、map

2.1 map介绍

map的文档介绍
在这里插入图片描述
可以看到,map有两个键值Key和T,后面统称T为Value,这是一个KV模型。

map通常也被实现为平衡二叉搜索树(红黑树),因此它也具备set的基本特性:有序性、唯一性、高效查找。

与set不同的是,Key值是可以修改的,迭代器底层代码:
在这里插入图片描述
我们来看看节点的底层代码:
在这里插入图片描述

键值对

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

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){}
};

在这里插入图片描述

map的两个键值就被设计为了键值对,其中Key为键值,Value表示与key对应的信息。pair<Key, Value>

可以看到,map是一个值对应另一个值的,就和数学的函数一样,并且,它是有序且不重复的(Value是可以重复的)。
map的本质功能:映射


2.2 map的使用

头文件和声明

#include <map>
using namespace std;map<string, int> studentScores;  // 键是string,值是int
2.2.1 插入元素

在这里插入图片描述
常用的是single element。
可以看到,函数参数的类型为pair<T1, T2>。
我们有如下两种方式来设计参数:

  • 方式1:
    在这里插入图片描述
    通过make_pair创建一个pair对象,用pair对象去做参数。

    void test_map()
    {map<string, string> dict;dict.insert(make_pair("string", "字符串"));dict.insert(make_pair("sort", "排序"));dict.insert(make_pair("insert", "插入"));
    }
    
  • 方式2:
    直接用{Key, Value}
    原理:C++11 多参数的构造函数隐式类型转换

    dict.insert({ "string", "字符串" });
    

注意:插入过程只比较Key,有相同的就插入失效,Value相不相同是无所谓的。

2.2.2 操作接口

在这里插入图片描述
这些接口作用和set是相同的,包括存在mutilmap,它也是突破了map的唯一性。

2.2.3 元素访问

与set相比,map重载了访问操作符[]
在这里插入图片描述
at()函数不常用
我们来看看map是如何访问的。
读读下面的文档
在这里插入图片描述
我们来看看它的底层代码:
在这里插入图片描述
有点晦涩,简化版:

V& operator[](const K& key)
{pair<iterator, bool> ret = insert(make_pair(key, V());return ret.first->second;
}

可以看出:[]的本质是insert

  1. 如果key在map中存在,返回pair<key为键值所在的节点的iterator, false>
  2. 如果key在map中不存在,返回pair<新插入的一个key为键值的节点的iterator, true>

总而言之,最终实现的功能是:

对于mymap[key]

  • 如果key存在:以key值为下标,返回value的值。
  • 如果key不存在:插入一个key值节点,返回一个空的value值

结语

相信你现在已经学会使用map和set了,不妨来做做题吧~
试试用map或set来解决它们:

  • 有效括号
  • 随机链表的复制
  • 前K个高频单词(注意排序的稳定性问题)

如果你做过这些题,那再好不过了,试试用map或set解决它们,感受它们带来的便捷。


文章转载自:
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://.
http://www.dtcms.com/a/280181.html

相关文章:

  • Dify的默认端口怎么修改
  • Spring Security 实践及源码学习
  • 焊接机器人智能节气阀
  • springboot3.5.3依赖学习
  • [BrowserOS] Nxtscape浏览器核心 | 浏览器状态管理 | 浏览器交互层
  • 响应式编程入门教程第三节:ReactiveCommand 与 UI 交互
  • 【HarmonyOS】ArkUI-X 跨平台框架入门详解(一)
  • HarmonyOS从入门到精通:自定义组件开发指南(八):组件插槽 (Slot) 的魅力
  • LabVIEW电铲电机远程监测
  • JVM——编译执行于解释执行的区别是什么?JVM使用哪种方式?
  • Postgres介绍(PostgreSQL)(开源对象关系型数据库管理系统)(与Mysql对比)
  • 如何加固Web服务器的安全?
  • 网页源码保护助手 海洋网页在线加密:HTML 源码防复制篡改,密文安全如铜墙铁壁
  • 021_自然语言处理应用
  • 网络劫持对用户隐私安全的影响:一场无形的数据窃取危机
  • 线上项目-升级redis8.0.3遇到的错
  • 基于按键开源MultiButton框架深入理解代码框架(二)(指针的深入理解与应用)
  • 【机器学习基础【5】】Python数据科学三件套:从数据创建到处理再到可视化实战
  • 常用高频指令总结
  • 批量制作Word:如何根据表格数据的内容批量制作word,根据Excel的数据批量制作word文档的步骤和注意事项
  • 遥感数据与作物生长模型同化及在作物长势监测与估产中的应用
  • 介绍InfiniRetri
  • 闲庭信步使用图像验证平台加速FPGA的开发:第十六课——图像五行缓存的FPGA实现
  • 小智完整MCP交互流程(以调节音量为例)
  • 学习秒杀系统-实现秒杀功能(商品列表,商品详情,基本秒杀功能实现,订单详情)
  • OpenAI GPT-4o技术详解:全能多模态模型的架构革新与生态影响
  • AI问答-测试:理解冒烟测试(Smoke Testing)
  • 背包问题(包括路径统计)
  • Android Studio模拟器报错
  • 边缘计算网关和云网关哪个更适合工厂实时控制?