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

C++——STL

STL分为:Algorithm(算法)、Container(容器)、Iterator(迭代器)。

细一点的话:容器、算法、迭代器、仿函数、适配器、空间配置器。

常见的STL容器:

1. 序列容器

  • vector(向量): std::vector 是⼀个动态数组实现,提供⾼效的随机访问和在尾部进⾏插⼊/删除操作。
  • list(链表): std::list 是⼀个双向链表实现,⽀持在任意位置进⾏插⼊/删除操作,但不⽀持随机访问。
  • deque(双端队列): std::deque 是⼀个双端队列实现,允许在两端进⾏⾼效插⼊/删除操作。
  • array(数组): std::array 是⼀个固定⼤⼩的数组实现,提供对数组元素的⾼效随机访问。
  • forward_list(前向链表): std::forward_list 是⼀个单向链表实现,只能从头到尾进⾏遍历,不⽀持双向访问。

2. 关联容器

  • set(集合): std::set 是⼀个有序的集合,不允许重复元素,⽀持快速查找、插⼊和删除。
  • multiset(多重集合): std::multiset 是⼀个有序的多重集合,允许重复元素
  • map(映射): std::map 是⼀个有序的键值对集合,不允许重复的键,⽀持快速查找、插⼊和删除。
  • multimap(多重映射): std::multimap 是⼀个有序的多重映射,允许重复的键
  • unordered_set(⽆序集合): std::unordered_set 是⼀个⽆序的集合,不允许重复元素,⽀持快速查找、插 ⼊和删除。
  • unordered_multiset(⽆序多重集合): std::unordered_multiset 是⼀个⽆序的多重集合,允许重复元素。
  • unordered_map(⽆序映射): std::unordered_map 是⼀个⽆序的键值对集合,不允许重复的键,⽀持快速 查找、插⼊和删除。
  • unordered_multimap(⽆序多重映射): std::unordered_multimap 是⼀个⽆序的多重映射,允许重复的 键。

3. 容器适配器

  • stack(栈): std::stack 是⼀个基于底层容器的栈实现,默认使⽤
  • queue(队列): std::deque 。 std::queue 是⼀个基于底层容器的队列实现,默认使⽤ std::deque 。
  • priority_queue(优先队列): std::priority_queue 是⼀个基于底层容器的优先队列实现,默认使⽤ std::vector 。

pair容器

保存两个数据成员,⽤来⽣成特定类型的模板。

pair<T1, T2>p;

对map进行插入,元素类型是pair

p.insert({word, 1});
p.insert(pair<string, int>(word, 1));

vector

Vector在堆中分配了⼀段连续的内存空间来存放元素

vector扩容

如果集合已满,在新增数据的时候,就要分配⼀块更⼤的内存,将原来的数据复制过来,释放之前的内存,在插⼊ 新增的元素 所以对vector的任何操作,⼀旦引起空间重新配置,指向原vector的所有迭代器就都失效了

vector有两个函数,⼀个是capacity(),在不分配新内存下最多可以保存的元素个数,另⼀个size(),返回当前已经存储数据的个数。

capacity和size相等时,vector就会扩容,capacity变⼤(翻倍)

扩容有

1、固定扩容

  • 机制: 每次扩容的时候在原 capacity 的基础上加上固定的容量,⽐如初始 capacity 为100,扩容⼀次为 capacity + 20, 再扩容仍然为 capacity + 20;
  • 缺点: 考虑⼀种极端的情况,vector每次添加的元素数量刚好等于每次扩容固定增加的容量 + 1,就会造成⼀种情况,每添加⼀次元素就需要扩容⼀次,⽽扩容的时间花费⼗分⾼昂。所以固定扩容可能会⾯临多次扩容的情况,时间复杂 度较⾼;
  • 优点: 固定扩容⽅式空间利⽤率⽐较⾼。

2、加倍扩容

  • 机制: 每次扩容的时候原 capacity 翻倍,⽐如初始capcity = 100, 扩容⼀次变为 200, 再扩容变为 400;
  • 优点: ⼀次扩容 capacity 翻倍的⽅式使得正常情况下添加元素需要扩容的次数⼤⼤减少(预留空间较多),时间复杂度较 低;
  • 缺点: 因为每次扩容空间翻倍,⽽很多空间没有利⽤上,空间利⽤率不如固定扩容。 在实际应⽤中,⼀般采⽤空间换时间的策略。

list

每个元素都是放在⼀块内存中,他的内存空间可以是不连续的,通过指针来进⾏数据的访问

在哪⾥添加删除元素性能都很⾼,不需要移动内存,当然也不需要对每个元素都进⾏构造与析构了,所以常⽤来做 随机插⼊和删除操作容器

双向链表,list每次插⼊新节点都会进⾏内存申请

deque

⽀持快速随机访问,由于deque需要处理内部跳转,因此速度上没有vector快。

deque是⼀个双端开⼝的连续线性空间,其内部为分段连续的空间组成,随时可以增加⼀段新的空间并链接

deque采⽤⼀块map作为主控,其中的每个元素都是指针,指向另⼀⽚连续线性空间,称之为缓存区,这个区才是 ⽤来储存数据的。

deque除了维护⼀个map指针以外,还维护了start与finish迭代器分别指向第⼀缓冲区的第⼀个元素,和最后⼀个 缓冲区的最后⼀个元素的下⼀个元素,同时它还必须记住当前map的⼤⼩。

stack && queue

栈与队列被称之为duque的配接器,其底层是以deque为底部架构。通过deque执⾏具体操作

heap(堆)

建⽴在完全⼆叉树上,分为两种,⼤根堆,⼩根堆

map && set

map内部实现了⼀个红⿊树(红⿊树是⾮严格平衡的⼆叉搜索树,⽽AVL是严格平衡⼆叉搜索树),红⿊树有⾃动 排序的功能,因此map内部所有元素都是有序的,红⿊树的每⼀个节点都代表着map的⼀个元素。因此,对于map 进⾏的查找、删除、添加等⼀系列的操作都相当于是对红⿊树进⾏的操作。map中的元素是按照⼆叉树(⼜名⼆叉 查找树、⼆叉排序树)存储的,特点就是左⼦树上所有节点的键值都⼩于根节点的键值,右⼦树所有节点的键值都 ⼤于根节点的键值。使⽤中序遍历可将键值按照从⼩到⼤遍历出来。

都是C++的关联容器,只是通过它提供的接⼝对⾥⾯的元素进⾏访问,底层都是采⽤红⿊树实现。

set:⽤来判断某⼀个元素是不是在⼀个组⾥⾯。

map:映射,相当于字典,把⼀个值映射成另⼀个值,可以创建字典。

map && unordered_map

map底层是基于红⿊树实现的,因此map内部元素排列是有序的。

unordered_map底层则是基于哈希表实现的,因此其元素的排列顺序是杂乱⽆序的。

时间复杂度:map是O(log n); unordered_map是O(1)

push_back && emplace_back

push_back ⽤于在容器的尾部添加⼀个元素。

emplace_back ⽤于在容器的尾部直接构造⼀个元素。

模板

模板分为类模板与函数模板,特化分为特例化(全特化)和部分特例化(偏特化)。 对模板特例化是因为对特定类型,可以利⽤某些特定知识来提⾼效率,⽽不是使⽤通⽤模板。

函数模板,只有全特化,偏特化的功能可以通过函数的重载完成。

对主版本模板类、全特化类、偏特化类的调⽤优先级从⾼到低进⾏排序是:全特化类>偏特化类>主版本模板类。

模板允许我们编写与数据类型无关的代码,减少了重复代码,提高代码可重用性。

因为模板会在编译时生成具体类型的代码,可能会导致编译时间显著增加。

函数模板

用于创建可以接受不同类型参数的函数,我们定义一个一次性模板,然后生成多个函数版本。

template <typename T>
T max(T a, T b) {return (a > b) ? a : b;
}

编译器在实际调用函数时,根据传入参数的类型自动生成具体类型的函数。

类模板

用于创建可以接受不同类型参数的类,通过创建一次模板类,我们可以生成多个不同类型的类实例

template <typename T>
class Stack {
private:std::vector<T> elements;
public:void push(T const& elem) { elements.push_back(elem); }void pop() { elements.pop_back(); }T top() const { return elements.back(); }
};

在使用类模板时,我们需要显式地声明模板类型

Stack<int> intStack;
Stack<double> doubleStack;

http://www.dtcms.com/a/391639.html

相关文章:

  • 「ECG信号处理——(25)基于ECG心率变异性(HRV)与EDA皮肤电活动的生理状态分析」2025年9月19日
  • 高通camx架构学习(四)——Camera Framework
  • 接口安全攻防战:从入门到精通的全方位防护指南
  • GEO(Generative Engine Optimization)技术详解与2025实践指南
  • Amazon SES 移出沙盒完整指南 高通过率模板
  • 从 IP over 鸽子到 TCP 的适应性
  • 大模型提示工程
  • 鸿蒙应用开发——Repeat组件的使用
  • 远程控制的全球节点功能如何开启?插件类型、并发数量怎么选?
  • 因果推断:因果回归树处理异质性处理效应(三)
  • 六应用层-真题
  • python笔记之正则篇(四)
  • 无标题文档
  • LeetCode 面试经典 150 题之验证回文串:双指针解题思路详解
  • pandas在AI中与其他库的协作
  • 【软件测试】第5章 测试分类(下)
  • 二物理层-真题-
  • c康复训练 01
  • MLP和CNN在图片识别中的对比——基于猫狗分类项目的实战分析
  • Node-Choice
  • PyQt6之滚动条
  • 使用OpenVINO将PP-OCRv5模型部署在Intel显卡上
  • 【图像处理基石】图像复原方面有哪些经典算法?
  • setTimeout定时器不生效- useRef 的特点/作用
  • 钻井的 “导航仪”:一文读懂单点、多点与随钻测量
  • CKS-CN 考试知识点分享(8) ingress 公开 https 服务
  • ​​[硬件电路-259]:LM4040AIM3 精密电压基准源: 管脚定义、概述、功能、技术指标、使用场景、原理
  • C语言:实现阶乘和计算
  • 鸿蒙应用开发——AppStorageV2和PersistenceV2的使用
  • shell脚本实现docker镜像批量保存并上传至Harbor仓库