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

STL 1 容器

STL 的核心思想是将算法与数据结构分离,通过模板让两者都能独立于具体数据类型,从而实现 “一次编写,多场景复用”。其设计遵循以下原则:

  • 接口抽象化:定义统一的接口(如迭代器、容器方法),使算法可适配不同数据结构。
  • 组件交互性:组件间通过明确的协议(如迭代器概念)协同工作,降低耦合度。
  • 性能优化:在泛型基础上保证效率,避免过度抽象导致的性能损耗。

文章目录

    • 1.容器
      • 1.容器的共性与差异
        • 1.共性操作
        • 2.差异点
    • 2.Vector
      • 1.本质与特性
      • 2.核心优势
      • 3.元素访问
      • 4.容量管理
        • 1.常用接口
        • 2.扩容机制
    • 2.list
      • 1.本质与特性
      • 2.优势
      • 3.局限性
      • 4.常用操作
    • 3.Set
      • 1.本质与特性
      • 2.常用操作
      • 3.set 为什么提供了find函数,而vector和list未提供
    • 4.unordered_set
      • 1.本质与特性
      • 2.优势
      • 3.局限性
      • 4.哈希冲突和元素重复
    • 5.Map
      • 1.本质与特性
      • 2.优势
      • 3.局限性

1.容器

容器是 C++ 编程中用于存储和管理数据的数据结构,其核心特点是通过模板技术实现了数据类型的抽象,使得容器可以存储任意类型的数据,同时提供了统一的接口来操作数据。

1.容器的共性与差异

1.共性操作

大多数容器支持以下基本操作:
1.元素插入:insert()、push_back() 等;
2.元素删除:erase()、pop_back() 等;
3.元素访问:front()、back()、迭代器遍历等;
4.容量查询:size()、empty() 等。

2.差异点

1.访问效率:vector 和 deque 支持随机访问(时间复杂度 O (1)),list 和 forward_list 只能顺序访问;
2.插入 / 删除效率:list 在任意位置插入 / 删除效率更高(O (1)),vector 尾部操作高效,中间操作需移动元素(O (n));
3.有序性:set/map 基于红黑树实现有序存储,unordered_set/unordered_map 基于哈希表实现无序存储;
4.内存管理:vector 可能预分配内存,list 动态分配节点内存。

2.Vector

1.本质与特性

1.动态数组:连续存储元素,支持随机访问(通过索引直接访问任意元素)。
2.自动扩容:当容量不足时,自动重新分配更大的内存空间,并复制原有元素。
3.内存连续:元素在内存中连续排列,可转换为普通数组指针(如 &vec[0])。

2.核心优势

1.随机访问高效:时间复杂度 O (1),支持 [] 和 at() 操作。
2.尾部插入 / 删除高效:平均时间复杂度 O (1)(扩容时可能为 O (n))。
3.与 C 语言兼容:可通过 data() 方法获取底层数组指针。

3.元素访问

1.vec[0] = 10; // 不检查越界,直接访问
2.vec.at(1) = 20; // 检查越界,抛出 std::out_of_range 异常
3.int front = vec.front(); // 返回首个元素
4.int back = vec.back(); // 返回最后一个元素
5.int* ptr = vec.data(); // 获取底层数组指针(C++11)
6.查找算法:std::find

4.容量管理

1.常用接口

1.size_t s = vec.size(); // 返回当前元素数量
2.size_t c = vec.capacity(); // 返回当前容量
3.bool empty = vec.empty(); // 判断是否为空
4.vec.resize(20); // 调整大小,新增元素默认初始化
5.vec.resize(20, 99); // 调整大小,新增元素用 99 初始化
6.vec.reserve(100); // 预分配至少 100 个元素的空间
7.vec.shrink_to_fit(); // 释放多余内存(C++11)

2.扩容机制

1 容量增长策略
1.当 push_back() 导致元素数量超过容量时,vector 通常会按 2 倍 或 1.5 倍 扩容(具体实现取决于编译器)。
2.扩容会触发 内存重新分配 和 元素复制,导致性能开销。

2.避免方法
// 预分配足够空间,避免多次扩容
std::vector vec;
vec.reserve(1000); // 一次性分配足够空间for (int i = 0; i < 1000; ++i) {
vec.push_back(i); // 无需扩容}

2.list

1.本质与特性

1.双向链表:由节点(Node)组成,每个节点包含元素值、前驱指针和后继指针。
2.动态内存分配:元素不连续存储,通过指针连接。
3.任意位置操作高效:插入和删除操作时间复杂度为 O (1)。

2.优势

1.插入 / 删除高效:在任意位置插入 / 删除元素无需移动其他元素。
2.迭代器稳定性:插入和删除操作不会使其他位置的迭代器失效。

3.局限性

1.不支持随机访问:访问元素需从头或尾遍历(时间复杂度 O (n))。
2.缓存不友好:元素分散存储,不利于 CPU 缓存优化。

4.常用操作

1.删除元素
1.erase() 是迭代器驱动的精确删除工具,适合需要控制删除位置的场景。
2.remove() 是值驱动的批量删除工具,适合需要清除特定值的场景。

2.算法
std::find

3.Set

set 是 C++ STL 中的关联容器,用于存储唯一元素并自动排序。默认升序

1.本质与特性

1.有序存储:元素按升序排列(默认使用 std::less 比较器)。
2.唯一性:每个元素只能出现一次,插入重复元素会被忽略。
3.基于红黑树:底层实现为平衡二叉搜索树(红黑树),保证插入、删除、查找操作的时间复杂度为 O (log n)。

2.常用操作

1.元素删除
s.erase(42); // 删除值为 42 的元素
s.erase(s.find(3)); // 删除迭代器指向的元素

2.查找算法
自身实现了find方法
auto it = s.find(42);

3.set 为什么提供了find函数,而vector和list未提供

底层结构决定查找效率
1.set 的红黑树结构
1.set 基于平衡二叉搜索树(红黑树)实现,插入、删除、查找的时间复杂度均为 O(log n)。
2.find() 可直接利用树的有序性,通过比较键值快速定位元素(类似二分查找)。

2.vector 和 list 的线性结构
1.vector 和 list 存储元素是无序的(除非用户手动排序),查找需遍历所有元素,时间复杂度为 O(n)。
2.这种情况下,提供 find() 成员函数并无优势,因为标准库已提供通用的 std::find 算法,无需为特定容器重复设计。

4.unordered_set

1.本质与特性

1.无序存储:元素根据哈希值散列存储,遍历时顺序不确定。
2.唯一性:每个元素只能出现一次,插入重复元素会被忽略。
3.基于哈希表:底层使用哈希表实现,平均插入、删除、查找时间复杂度为 O (1)。

2.优势

1.快速查找:平均 O (1) 时间复杂度(优于 set 的 O (log n))。
2.元素唯一性:自动去重,无需手动检查。

3.局限性

1.无顺序保证:遍历时元素顺序可能与插入顺序不同。
2.哈希冲突开销:极端情况下性能可能退化为 O (n)。
3.自定义类型需额外工作:需自定义哈希函数和相等比较器。

4.哈希冲突和元素重复

1.哈希冲突
1.哈希函数的作用:将任意类型的元素映射到一个固定范围的整数(哈希值)。例如,unordered_set 用哈希值确定元素存储的桶位置。
2.冲突的必然性:由于哈希值范围有限(如 size_t 类型),而元素可能无限多,根据鸽巢原理,必然存在不同元素映射到相同哈希值的情况。

2.元素重复
元素重复是值语义层面的问题:
1.unordered_set 通过 operator== 判断元素是否相同。
2.当插入元素时,若集合中已存在 operator== 相等的元素,则插入操作会被忽略。

3.先后顺序
1.哈希冲突
2.重复的判断

5.Map

std::map 是 C++ STL 中的关联容器,用于存储键值对(Key-Value)并按键自动排序。默认升序

1.本质与特性

1.有序存储:元素按键(Key)升序排列(默认使用 std::less 比较器)。
2.唯一性:每个键(Key)只能出现一次,插入重复键会被忽略或覆盖原值。

  • 覆盖:使用 operator[] 或 insert_or_assign。
  • 忽略:使用 insert、emplace 或 try_emplace。

3.基于红黑树:底层实现为平衡二叉搜索树(红黑树),保证插入、删除、查找操作的时间复杂度为 O (log n)。

2.优势

1.自动排序:元素按键自动有序,遍历时按顺序输出。
2.高效查找:基于键的快速查找(O (log n))。
3.键值映射:适合存储字典、配置等需要键值关联的数据。

3.局限性

1.不支持随机访问:无法通过索引直接访问元素(如 map[0] 无效)。
2.插入 / 删除开销:每次操作需维护树的平衡,比 unordered_map 略慢。

http://www.xdnf.cn/news/953821.html

相关文章:

  • 基于生态系统服务(InVEST模型)的人类活动、重大工程生态成效评估、论文写作
  • 12.找到字符串中所有字母异位词
  • Oracle查询表空间大小
  • vue的<router-link>的to里面的query和params的区别
  • pocketflow库实现guardrail
  • Nginx server_name 配置说明
  • Qt插件化编程的全面解析(QPluginLoader)
  • 微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
  • 云防火墙(安全组)配置指南:从入门到精通端口开放 (2025)
  • OCR、图像分类与目标检测
  • 雷达RCS计算中的旋转矩阵
  • 在Ubuntu上利用loongarch64交叉编译工具编译opencv4.4.0
  • 【排错】ollama报错unable to load model
  • 【知识点】第8章:程序设计方法论
  • CKA考试知识点分享(6)---PriorityClass
  • 自动化测试工具playwright中文文档-------19.评估JavaScript
  • 初版BL程序一些细节整理(碎碎念)
  • 相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
  • 无线耳机存储痛点解决方案-64Mb Quad-SPI Pseudo-SRAM CS56404L
  • 向量几何的二元性:叉乘模长与内积投影的深层联系
  • 安宝特方案丨从依赖经验到数据驱动:AR套件重构特种装备装配与质检全流程
  • SQL注入篇-sqlmap的配置和使用
  • 分布式计算框架学习笔记
  • 我的世界Java版1.21.4的Fabric模组开发教程(十二)方块状态
  • UE5 文本框自动换行
  • 苍穹外卖--缓存菜品
  • 用docker来安装部署freeswitch记录
  • “一张网,万般用”——聊聊网络虚拟化到底怎么实现的
  • 大话软工笔记—记录形式
  • React从基础入门到高级实战:React 实战项目 - 项目五:微前端与模块化架构