STL中各类容器详细介绍

STL介绍

STL(Standard Template Library),即标准模板库,是一个具有工业强度的,高效的C++程序库。它被容纳于C++标准程序库(C++ Standard Library)中,是ANSI/ISO C++标准中最新的也是极具革命性的一部分。该库包含了诸多在计算机科学领域里所常用的基本数据结构和基本算法。为广大C++程序员们提供了一个可扩展的应用框架,高度体现了软件的可复用性。

C++STL提供的数据结构

1. Sequence Containers:维持顺序的容器。

(a). vector:

动态数组,在堆中分配内存,是我们最常使用的数据结构之一。

特点:

  • 底层结构 : 底层由 动态数组 实现 , 特点是 存储空间 连续 ;
  • 访问遍历 : 支持 随机访问迭代器 , 可使用下标访问 , 访问元素非常快 O(1) 复杂度 ;
  • 插入 / 删除 : 尾部插入 / 删除效率高 O(1) 复杂度 ; 中间 和 头部插入/删除效率低 , 由于存储空间连续 , 需要将插入 / 删除位置之后的元素依次改变位置 , O(n) 复杂度 ;
  • 空间效率 : 底层实现时 , 会事先预留一些额外空间 , 以减少重新分配的次数 ;
  • 使用场景 : 需要 随机访问 且 频繁在尾部进行操作 的场景 ; 如果频繁增删元素 则 不适用该容器 ;

时间复杂度:

实现原理:

简单理解,就是vector是利用上述三个指针来表示的,基本示意图如下:
在这里插入图片描述
两个关键大小:
大小:size=_Mylast - _Myfirst;
容量:capacity=_Myend - _Myfirst;
分别对应于resize()、reserve()两个函数。


size表示vector中已有元素的个数,capacity表示vector最多可存储的元素的个数;

为了降低二次分配时的成本,vector实际配置的内存空间大小会比客户需求的更大一些,以备将来扩充,这就是capacity的概念。即capacity>=size,当等于时,容器此时已满,若再要加入新的元素时,就要重新进行内存分配,整个vector的数据都要移动到新内存。

vector:扩容机制:

vector 容器扩容的过程需要经历以下 3 步:

1. 完全弃用现有的内存空间,重新申请更大的内存空间;

2. 将旧内存空间中的数据,按原有顺序移动到新的内存空间中;

3. 最后将旧的内存空间释放。

因为 vector 扩容需要申请新的空间,所以扩容以后它的内存地址会发生改变。vector 扩容是非常耗时的,为了降低再次分配内存空间时的成本,每次扩容时 vector 都会申请比用户需求量更多的内存空间(这也就是 vector 容量的由来,即 capacity>=size),以便后期使用。VS里面扩容机制是1.5倍扩容,gcc里面是2倍扩容。


(b). list:

双向链表,也可以当作 stack 和 queue 来使用。有个缺点,链表不支持快速随机读取。

特点

  • 底层结构 : 底层由 双向链表 实现 , 特点是 存储空间 不连续 ;
  • 访问遍历 : 不支持 随机访问迭代器 , 只能通过迭代器进行访问 ;
  • 插入 / 删除 : 任意位置 插入 / 删除 效率都很高 ;
  • 空间效率 : 每个元素 都需要 分配额外的空间 , 存储 当前元素的 前驱元素 和 后继元素 ;
  • 使用场景 : 需要 在任意位置 频繁 插入 / 删除 操作的 场景 ;

时间复杂度:


(c). deque:

双端队列, 是一种优化了的、对序列两端元素进行添加和删除操作的基本序列容器。它允许较为快速地随机访问,但它不像vector 把所有的对象保存在一块连续的内存块,而是采用多个连续的存储块,并且在一个映射结构中保存对这些块及其顺序的跟踪。向deque 两端添加或删除元素的开销很小。它不需要重新分配空间,所以在两端端增删元素比vector 更有效。

特点:

  • 底层结构 : 底层由 双向队列 实现 , 特点是 存储空间 连续 ;
  • 访问遍历 : 支持 随机访问迭代器 , 其性能比 vector 动态素组要低 ;
  • 插入 / 删除 : 头部 和 尾部 插入 / 删除效率高 , O(1) 复杂度 ; 中间 插入/删除效率低 , 由于存储空间连续 , 需要将插入 / 删除位置之后的元素依次改变位置 , 比 vector 动态数组要快一些 ;
  • 空间效率 : 底层实现时比 vector 的结构要复杂 , 也会事先预留一些额外空间 , 以减少重新分配的次数 ;
  • 使用场景 : 需要 随机访问 且 频繁在 首部 和 尾部 进行操作 的场景 ; 如果频繁 在中部 增删元素 则 不适用该容器 ;

实现原理:

deque 是由一段一段的定量的连续空间构成。一旦有必要在 deque 前端或者尾端增加新的空间,便配置一段连续定量的空间,串接在 deque 的头端或者尾端。deque 最大的工作就是维护这些分段连续的内存空间的整体性的假象,并提供随机存取的接口,避开了重新配置空间,复制,释放的轮回,代价就是复杂的迭代器架构。
既然 deque 是分段连续内存空间,那么就必须有中央控制,维持整体连续的假象,数据结构的设计及迭代器的前进后退操作颇为繁琐。

deque 采取一块所谓的 map(不是 STL 的 map 容器)作为主控,这里所谓的 map 是一小块连续的内存空间,其中每一个元素(此处成为一个结点)都是一个指针,指向另一段连续性内存空间,称作缓冲区。缓冲区才是 deque的存储空间的主体。

时间复杂度:


(d). array:

固定大小的数组,一般在刷题时我们不使用。


(e). forward_list:

单向链表,一般在刷题时我们不使用。


2. Container Adaptors:基于其它容器实现的数据结构。

(a). stack:

后入先出(LIFO)的数据结构,默认基于 deque 实现。stack 常用于深度优先搜
索、一些字符串匹配问题以及单调栈问题。


(b). queue:

先入先出(FIFO)的数据结构,默认基于 deque 实现。queue 常用于广度优先
搜索。


(c). priority_queue:

最大值先出的数据结构,默认基于vector实现堆结构。它可以在O(n log n)
的时间排序数组,O(log n) 的时间插入任意值,O(1) 的时间获得最大值,O(log n) 的时
间删除最大值。priority_queue 常用于维护数据结构并快速获取最大或最小值。


3. Associative Containers:实现了排好序的数据结构。

(a). set:

有序集合,元素不可重复,底层实现默认为红黑树,它可以在 O(n log n) 的时间排序数组,O(log n) 的时间插入、删除、查找任何节点。这里注意,set 和 priority_queue 都可以用
于维护数据结构并快速获取最大最小值,但是它们的时间复杂度和功能略有区别,如
priority_queue 默认不支持删除任意值,而 set 获得最大或最小值的时间复杂度略高,具
体使用哪个根据需求而定。

特点:

  • 底层结构 : 底层由 红黑树 实现 , 红黑树 是 一种 平衡二叉搜索树 , 存储空间 不连续 ;
  • 访问遍历 : 不支持 随机访问迭代器 , 不能通过过下标访问 , 只能通过迭代器进行访问 ;
  • 插入 / 删除 : 查询 / 插入 / 删除 效率 为 O(log n) 复杂度 ;
  • 排序方式 : 默认使用 less 仿函数 , 即 < 运算符进行排序 ; 也可以自定义 排序规则 仿函数 ;
  • 使用场景 : 需要 有序集合 且 元素 不重复 的场景 ;

时间复杂度:

增删改查都近似 = O(log N)


(b). multiset:

支持重复元素的 set。

(c). map:

有序映射或有序表,在 set 的基础上加上映射关系,可以对每个元素 key 存一个
值 value。

特点:

  • 底层结构 : 底层由 红黑树 实现 , 红黑树 是 一种 平衡二叉搜索树 , 存储空间 不连续 ; 存储的 元素 是 键值对 元素 ;
  • 访问遍历 : 不支持 随机访问迭代器 , 不能听过下标访问 , 只能通过迭代器进行访问 ;
  • 插入 / 删除 : 查询 / 插入 / 删除 效率 为 O(log n) 复杂度 ; 与 set 集合容器相同 ;
  • 排序方式 : 默认使用 less 仿函数 , 即 < 运算符进行排序 ; 也可以自定义 排序规则 仿函数 ; map 映射容器 不允许重复的键 , multimap 多重映射容器允许重复的键 ;
  • 使用场景 : 需要 有序 键值对 且 元素 不重复 的场景 ;
std::map 映射容器 与 std::set 集合容器 的区别是
map 容器存储的是 键值对 元素 , 元素是 pair  
set 容器 存储的是 单纯的 键 单个元素 ;

时间复杂度:

增删改查都近似 = O(log N)


(d). multimap:

支持重复元素的 map。


4. Unordered Associative Containers:对每个 Associative Containers 实现了哈希版本。

(a). unordered_set:

哈希集合,可以在 O(1) 的时间快速插入、查找、删除元素,常用于快
速的查询一个元素是否在这个容器内。


(b). unordered_multiset:

支持重复元素的 unordered_set。


(c). unordered_map:

哈希映射或哈希表,在 unordered_set 的基础上加上映射关系,可以对
每一个元素 key 存一个值 value。在某些情况下,如果 key 的范围已知且较小,我们也
可以用 vector 代替 unordered_map,用位置表示 key,用每个位置的值表示 value。


(d). unordered_multimap:

支持重复元素的 unordered_map。

STL 各容器使用场景示例

  • 如果需要 随机访问 , 则使用 vector 单端数组 或 deque 双端数组 容器 ;
  • 如果 需要 在 尾部 频繁 插入 / 删除 , 则使用 vector 单端数组 ;
  • 如果 需要 在 首部 和 尾部 频繁 插入 / 删除 , 则使用 deque 双端数组 ;
  • 如果 需要 在 任意位置 频繁 插入 / 删除 , 则使用 list 双向链表 ;
  • 如果需要保持 元素 有序 且 不重复 , 则使用 set 集合容器 ;
  • 如果需要保持 元素 有序 且 可重复 , 则使用 multiset 多重集合容器 ;
  • 如果不需要保持 元素 有序 , 可使用unordered_set, unordered_map;


————————————————
引用:

https://blog.csdn.net/zuihaobizui/article/details/119741156

https://blog.csdn.net/shulianghan/article/details/135363350

https://www.cnblogs.com/yinbiao/p/11636405.html

C++ vector的内部实现原理及基本用法_vector内部实现-CSDN博客

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

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

相关文章

Python | NCL风格 | EOF | 相关 | 回归

这里在linux系统上使用geocat实现NCL风格的图片绘制 geocat Linux上安装 geocat conda update condaconda create -n geocat -c conda-forge geocat-vizconda activate geocatconda update geocat-viz Dataset - NOAA Optimum Interpolation (OI) SST V2 # 海温月平均数据- lsm…

讲讲你对数据结构-线性表了解多少?

线性表 - 数组和矩阵 当谈到线性表时&#xff0c;数组和矩阵是两种常见的数据结构。 数组&#xff08;Array&#xff09;&#xff1a; 数组是有序的元素集合&#xff0c;可以通过索引来访问和操作其中的元素。它是最简单、最基本的数据结构之一。数组的特点包括&#xff1a; …

哈哈哈哈哈

欢迎使用Markdown编辑器 你好&#xff01; 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章&#xff0c;了解一下Markdown的基本语法知识。 222 我们对Markdown编辑器进行了一些功能拓展与语法支持&#xff0c;…

java replaceFirst抛出异常

问题描述 replace和replaceAll出现异常 问题原因 其中replace使用的是普通的KMP替换&#xff0c;而replaceAll和replaceFirst是正则表达式。 当出现特殊字符或者匹配正则表达式的时候&#xff08;常见是&#xff08;&#xff09;$^\&#xff09;&#xff0c;会直接出现正则表…

CSS基础:简单介绍CSS

你好&#xff0c;我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端的程序媛。大专生&#xff0c;2年时间从1800到月入过万&#xff0c;工作5年买房。 分享成长心得。 259篇原创内容-公众号 后台回复“前端工具”可获取开发工具&#xff0c;持续更新中 后台回复“前端基础…

java中Date类,SimpleDateFormat类和Calendar类

Date类 public Date() 创建一个Date对象&#xff0c;代表的是系统当前此刻的日期时间 public Date(long date) Constructs a Date object using the given milliseconds time value. 把时间毫秒值转变成Date日期对象 public void setTime(long date) Sets an existing Date ob…

SQLite下一代查询规划器(十)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLite 查询优化器概述&#xff08;九&#xff09; 下一篇&#xff1a;SQLite的架构&#xff08;十一&#xff09; 1. 引言 “查询规划器”的任务是弄清楚 找出完成 SQL 语句的最佳算法或“查询计划”。 从 SQLi…

顶象全系列产品升级,对抗AI带来的新威胁

4月2日&#xff0c;在顶象CSDN直播间&#xff0c;最新一期“业务安全大讲堂”上&#xff0c;顶象数据科学家翼龙与资深解决方案专家鳯羽&#xff0c;围绕当前备受关注的AI威胁、人脸风险进行深入分享&#xff0c;并详细介绍针对AI威胁的最新反欺诈技术与安全产品。 AI威胁带来的…

【信号处理】基于变分自编码器(VAE)的图片典型增强方法实现

关于 深度学习中&#xff0c;经常面临图片数据量较小的问题&#xff0c;此时&#xff0c;对数据进行增强&#xff0c;显得比较重要。传统的图片增强方法包括剪切&#xff0c;增加噪声&#xff0c;改变对比度等等方法&#xff0c;但是&#xff0c;对于后端任务的性能提升有限。…

面试复盘1 - 测试相关(实习)

写在前&#xff1a;hello&#xff0c;大家早中晚上好~这里是西西&#xff0c;最近有在准备测试相关的面试&#xff0c;特此开设了新的篇章&#xff0c;针对于面试中的问题来做一下复盘&#xff0c;会把我自己遇到的问题进行整理&#xff0c;除此之外还会进行对一些常见面试题的…

【解决】Unity Profile | FindMainCamera

开发平台&#xff1a;Unity 2020.3.7f1c1 关键词&#xff1a;FindMainCamera   问题背景 ModelViewer 是开发者基于 UnityEngine 编写的相机控制组件。ModelView.Update 中调度52次并触发3次GC.Collect。显然并不期望并尽可能避免 Update 造成的GC 问题。事实上 FindMainCame…

稀碎从零算法笔记Day35-LeetCode:字典序的第K小数字

要考虑完结《稀碎从零》系列了哈哈哈 这道题和【LC.42 接雨水】&#xff0c;我愿称之为【笔试界的颜良&文丑】 题型&#xff1a;字典树、前缀获取、数组、树的先序遍历 链接&#xff1a;440. 字典序的第K小数字 - 力扣&#xff08;LeetCode&#xff09; 来源&#xff1…