4.关联式容器

news2024/11/16 1:36:21

关联式container

STL中一些常见的容器:

  1. 序列式容器(Sequence Containers)

    • vector(动态数组): 动态数组,支持随机访问和在尾部快速插入/删除。
    • list(链表): 双向链表,支持在任意位置快速插入/删除。
    • deque(双端队列): 双端队列,支持在两端快速插入/删除。

    容器适配器(Container Adapters):

    • stack(栈): 后进先出(LIFO)的数据结构。
    • queue(队列): 先进先出(FIFO)的数据结构。
    • priority_queue(优先队列): 具有优先级的队列。

  2. 关联式容器(Associative Containers)

    • set(集合): 有序集合,不允许重复元素。
    • multiset(多重集合): 有序集合,允许重复元素。
    • map(映射): 键-值对的集合,按键有序存储,不允许重复键。
    • multimap(多重映射): 键-值对的集合,按键有序存储,允许重复键。

    无序关联容器(Unordered Associative Containers):

    • unordered_set: 无序集合,不允许重复元素。
    • unordered_multiset: 无序集合,允许重复元素。
    • unordered_map: 无序映射,按键无序存储,不允许重复键。
    • unordered_multimap: 无序映射,按键无序存储,允许重复键。

关联式容器

关联式容器是指数据是键值对的格式。容器内部结构(可能是RB-tree或者hash-table)便依照其键值大小,以某种特定规则将这个元素放置于合适的位置,关联式容器没有所谓头尾(只有最大元素和最小元素);所以不会有所谓push_back()push_front()等行为的操作。

1.set

set中所有元素都会根据元素的键值自动被排序。std::set 使用红黑树(一种自平衡的二叉搜索树)作为底层数据结构。

set的元素不像map那样可以同时拥有key和value,set的键值就是实值。并且set不允许两个元素拥有相同的值。

迭代器

std::set 的迭代器性质:

  1. 递增顺序: std::set 中的元素是有序排列的,迭代器按照递增(升序)的顺序遍历元素。这是由底层平衡二叉搜索树的特性决定的。
  2. 双向迭代器: std::set 提供双向迭代器,支持向前(++)和向后(-)遍历。
  3. 随机访问特性的缺失: 与支持随机访问的容器(如 std::vector)不同,std::set 的迭代器不支持 +nn 这样的随机跳跃,因为底层结构并不是一个连续的存储区域。
  4. 不能通过迭代器修改set键值,因为set的元素值关系到set元素的排列,随意改变值,会导致排列顺序崩溃,所以不不能通过迭代器修改set值。

因此插入和删除操作并不会使set迭代器失效。当然,被删除的哪个迭代器除外。


set的核心在于使用的红黑树的insert_unique插入数据。

在这里插入图片描述

2.map

map所有元素都会根据元素的键值自动被排序。std::map 也是使用红黑树(一种自平衡的二叉搜索树)作为底层数据结构。

map的所有元素都是pair,同时拥有实值(value)和键值(key)。pair的第一元素被视为键值,第二元素被视为实值。map不允许两个元素拥有相同的键值。

pair的定义:

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和set一样的核心在于使用的红黑树的insert_unique插入数据。

在这里插入图片描述

迭代器

map和set的迭代器性质一样。

  • 递增顺序
  • 双向迭代器
  • 随机访问特性缺少
  • 不能通过迭代器修改map键值。但是可以通过迭代器修改键值对应的实值。
int main() {
	std::map<int, std::string> myMap;

	// 插入元素
	myMap[1] = "One";
	myMap[2] = "Two";
	myMap[3] = "Three";

	// 使用迭代器遍历并修改值
	for (auto it = myMap.begin(); it != myMap.end(); ++it) {
		std::cout << "Key: " << it->first << ", Value: " << it->second << std::endl;

		//it->first = 4; //报错
		// 修改值
		it->second = "Modified";
	}
	for (auto it = myMap.begin(); it != myMap.end(); ++it) {
		std::cout << "Key: " << it->first << ", Value: " << it->second << std::endl;
	}
	return 0;
}

关联式容器的find方法

在这里插入图片描述

3.multiset

multiset的特性以及用法和set完全相同,唯一的差别在于它允许键值重复。

它的底层机制是使用RB-tree的insert_equal()而非insert_unique();

在这里插入图片描述

4.multimap

与map的用法完全相同,唯一的差别在于,它允许键值重复。

它的底层机制是使用RB-tree的insert_equal()而非insert_unique();

在这里插入图片描述

5.hashtable

上述提到的以红黑树做为底层结构的set、map,其查找的时间复杂度为对数,但是依赖于元素值是要有足够的随机性。例如输入数据完全有序或完全逆序,红黑树可能会退化成链表,导致性能下降至O(n)。

HashTable 是一种通过哈希函数将关键字映射到存储桶的数据结构。STL中的HashTable通常是一个数组,每个数组元素是一个链表或其他形式的容器。当有多个关键字哈希到同一个存储桶时,它们被放入同一个链表中。

使用哈希函数会遇到一个问题,可能有不同的元素被映射到相同的位置,这就是所谓的hash碰撞问题。解决hash碰撞问题有很多,包括线性探测、二次探测、开链法等。

线性探测

线性探测的基本操作:

  1. 插入操作

    • 根据散列函数计算键的散列值。
    • 如果该位置为空,则将键值对插入该位置。
    • 如果该位置已被占用,就向后线性探测,查找下一个空闲位置,直到找到一个空闲位置为止,然后插入键值对。
  2. 查找操作

    • 根据散列函数计算键的散列值。
    • 如果该位置为空,表示键不存在。
    • 如果该位置不为空,检查键是否匹配,如果匹配则找到了键,返回对应的值;否则,向后线性探测,查找下一个位置,直到找到匹配的键或者遇到空位置为止。
  3. 删除操作

    • 查找要删除的键。
    • 如果找到,将该位置标记为空,表示删除该键。注意:在某些实现中,可以使用特殊的标记表示已删除的位置,而不是直接将位置设置为空。被叫做惰性删除,实际的删除操作等到整理表的时候再删。

    具体的探测序列可以表示为:
    在这里插入图片描述

二次探测

二次探测是解决散列表冲突的一种方法,类似于线性探测,但是在寻找下一个可用位置时,不是简单地线性向后移动,而是使用一个二次方程来计算下一个位置。这样可以更灵活地处理冲突,减少聚集的可能性。
在这里插入图片描述
二次探测的优点是相对于线性探测,能够更好地分散冲突,减少聚集问题。然而,如果HashTable的大小选择不当,仍然可能发生聚集问题。

开链法

开链法的做法是为每一个表格元素维护一个list。通过哈希函数定位到某一个list,然后在那一个list上执行插入、搜寻、删除操作。

使用开链法,哈希表的负载系数将大于1。上述的线性探测和二次探测的负载系数都是小于1的。

开链法由一个bukets vector和一个bucket list组成。
在这里插入图片描述
在这里插入图片描述

迭代器

在这里插入图片描述

hash_set、hash_map、hash_multiset、hash_multimap

hash_set以hashtable为底层机制。由于hash_set所供应的操作接口。 注意:hash_table中没有自动排序功能。

hash_map、hash_multiset、hash_multimap基本都与对应的类型相同,只是底层机制由hash_table来进行实现。

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

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

相关文章

奇舞周刊第521期:“一切非 Rust 项目均为非法”

奇舞推荐 ■ ■ ■ 拜登&#xff1a;“一切非 Rust 项目均为非法” 科技巨头要为Coding安全负责。这并不是拜登政府对内存安全语言的首次提倡。“程序员编写代码并非没有后果&#xff0c;他们的⼯作⽅式于国家利益而言至关重要。”白宫国家网络总监办公室&#xff08;ONCD&…

Python3零基础教程之数学运算专题进阶

大家好,我是千与编程,今天已经进入我们Python3的零基础教程的第十节之数学运算专题进阶。上一次的数学运算中我们介绍了简单的基础四则运算,加减乘除运算。当涉及到数学运算的 Python 3 刷题使用时,进阶课程包含了许多重要的概念和技巧。下面是一个简单的教程,涵盖了一些常…

NOC2023软件创意编程(学而思赛道)python初中组决赛真题

目录 下载原文档打印做题: 软件创意编程 一、参赛范围 1.参赛组别:小学低年级组(1-3 年级)、小学高年级组(4-6 年级)、初中组。 2.参赛人数:1 人。 3.指导教师:1 人(可空缺)。 4.每人限参加 1 个赛项。 组别确定:以地方教育行政主管部门(教委、教育厅、教育局) 认…

嵌入式驱动学习第一周——linux的休眠与唤醒

前言 本文介绍进程的休眠与唤醒。 嵌入式驱动学习专栏将详细记录博主学习驱动的详细过程&#xff0c;未来预计四个月将高强度更新本专栏&#xff0c;喜欢的可以关注本博主并订阅本专栏&#xff0c;一起讨论一起学习。现在关注就是老粉啦&#xff01; 行文目录 前言1. 阻塞和非阻…

Doris实战——美联物业数仓

目录 一、背景 1.1 企业背景 1.2 面临的问题 二、早期架构 三、新数仓架构 3.1 技术选型 3.2 运行架构 3.2.1 数据模型 纵向分域 横向分层 数据同步策略 3.2.2 数据同步策略 增量策略 全量策略 四、应用实践 4.1 业务模型 4.2 具体应用 五、实践经验 5.1 数据…

【Java EE】线程安全的集合类

目录 &#x1f334;多线程环境使用 ArrayList&#x1f38d;多线程环境使⽤队列&#x1f340;多线程环境使⽤哈希表&#x1f338; Hashtable&#x1f338;ConcurrentHashMap ⭕相关面试题&#x1f525;其他常⻅问题 原来的集合类, 大部分都不是线程安全的. Vector, Stack, HashT…

EndNote 21:文献整理与引用,一键轻松搞定 mac/win版

EndNote 21是一款功能强大的文献管理软件&#xff0c;专为学术研究者、学生和教师设计。它提供了全面的文献管理解决方案&#xff0c;帮助用户轻松整理、引用和分享学术文献。 EndNote 21软件获取 EndNote 21拥有直观的用户界面和强大的文献检索功能&#xff0c;用户可以轻松地…

昇腾ACL应用开发之硬件编解码dvpp

1.前言 在我们进行实际的应用开发时&#xff0c;都会随着对一款产品或者AI芯片的了解加深&#xff0c;大家都会想到有什么可以加速预处理啊或者后处理的手段&#xff1f;常见的不同厂家对于应用开发的时候&#xff0c;都会提供一个硬件解码和硬件编码的能力&#xff0c;这也是抛…

【C++干货基地】揭秘C++11常用特性:内联函数 | 范围for | auto自动识别 | nullptr指针空值

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引入 哈喽各位铁汁们好啊&#xff0c;我是博主鸽芷咕《C干货基地》是由我的襄阳家乡零食基地有感而发&#xff0c;不知道各位的…

基于springboot实现校园爱心捐赠互助管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现校园爱心捐赠互助管理系统演示 摘要 随着互联网及电子商务平台的飞速发展&#xff0c;利用在线平台实现的二手商品交易以及在线捐赠已经非常普遍&#xff0c;很多高校目前还存在贫困生需要通过爱心人士的捐助来完成学业&#xff0c;同时很多高校的大学生也希…

【C++】STL学习之旅——初识STL,认识string类

string类 1 STL 简介2 STL怎么学习3 STL缺陷4 string4.1 初识 string4.2 初步使用构造函数成员函数 5 小试牛刀Thanks♪(&#xff65;ω&#xff65;)&#xff89;谢谢阅读&#xff01;&#xff01;&#xff01;下一篇文章见&#xff01;&#xff01;&#xff01; 1 STL 简介 …

PyCharm如何添加python库

1.使用pip命令在国内源下载需要的库 下面使用清华源&#xff0c;在cmd中输入如下命令就可以了 pip install i https://pypi.tuna.tsinghua.edu.cn/simple 包名版本号2.如果出现报错信息&#xff0c;Cannot unpack file…这种情况&#xff0c;比如下面这种 ERROR: Cannot unpa…

考研复试指南

1. 记住&#xff0c;复试的本质不是考试&#xff0c;而是一场自我展示。 考研复试并非简单的知识考察&#xff0c;更是一场展示自我能力和潜力的机会。除了学科知识&#xff0c;考官更关注你的综合素质、学术兴趣和未来发展规划。因此&#xff0c;要保持自信&#xff0c;用更全…

前端canvas项目实战——简历制作网站(五):右侧属性栏(字体、字号、行间距)

目录 前言一、效果展示二、实现步骤1. 优化代码&#xff0c;提取常量2. 实现3个编辑模块3. 实现updateFontProperty方法4. 一个常见的用法&#xff1a;仅更新当前选中文字的样式 三、Show u the code后记 前言 上一篇博文中&#xff0c;我们扩充了线条对象&#xff08;fabric.…

带你快速初步了解Python字典

1.字典 定义多个数据一般使用列表&#xff0c;但是列表也存在一定的缺陷 若列表中有多个元素&#xff0c;想访问其中某个元素&#xff0c;比较不方便 定义字典的语法&#xff1a;{key1:value1, key2:value2, key3:value3......} 字典和列表习惯的使用场景&#xff1a; &qu…

(3)(3.1) FlightDeck FrSky发射器应用程序

文章目录 前言 1 概述 2 Turnkey Packages 3 参数说明 前言 ​Craft and Theory 的 FlightDeck 可让你轻松查看飞行模式、高度、速度、姿态和关键系统警报&#xff0c;包括故障保护和电池错误&#xff0c;如电池不平衡警告和发射机低电量警报。 1 概述 Craft and Theory 的…

Jmeter 安装

JMeter是Java的框架&#xff0c;因此在安装Jmeter前需要先安装JDK&#xff0c;此处安装以Windows版为例 1. 安装jdk&#xff1a;Java Downloads | Oracle 安装完成后设置环境变量 将环境变量JAVA_HOME设置为 C:\Program Files\Java\jdk1.7.0_25 在系统变量Path中添加 C:\Pro…

【NR 定位】3GPP NR Positioning 5G定位标准解读(一)

目录 前言 1. 3GPP规划下的5G技术演进 2. 5G NR定位技术的发展 2.1 Rel-16首次对基于5G的定位技术进行标准化 2.2 Rel-17进一步提升5G定位技术的性能 3. Rel-18 关于5G定位技术的新方向、新进展 3.1 Sidelink高精度定位功能 3.2 针对上述不同用例&#xff0c;3GPP考虑按…

JAVAEE初阶 JVM(二)

垃圾回收和双亲委派模型 1.双亲委派模型2.垃圾回收机制(1) 识别垃圾1.引用计数2.可达性分析 (2) 销毁垃圾1.标记清除2.复制算法3.标记整理 3.分代回收 1.双亲委派模型 描述了如何查找.class文件的策略. 同时JVM中有专门进行类加载的操作,有一个模块,叫做类加载器. 上述就是为了…

安装Realtek Audio Driver失败[Error Code:-0001]

安装Realtek Audio Driver失败[Error Code&#xff1a;-0001] 首先来看一下我们遇到的问题GPT4的推荐解决方法&#xff08;流水账&#xff09;笔者自己真实有效的解决办法 首先来看一下我们遇到的问题 描述&#xff1a;在笔记本更新完电脑之后&#xff0c;没有自带声音驱动。然…