当前位置: 首页 > 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 略慢。

相关文章:

  • NoMachine 远程连接时遇到“黑屏
  • Shell循环(三)
  • MySQL故障排查、生产环境优化与存储引擎MyISAM和InnoDB
  • GruntJS-前端自动化任务运行器从入门到实战
  • 关于 JavaScript 中 new Set() 的详解
  • MacOS 安装git
  • ssm项目tomcat启动就java: Compilation failed: internal java compiler error
  • 在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
  • Leetcode4(寻找两个正序数组的中位数)
  • Windows11 WSL2 Ubuntu编译安装perf工具
  • VSCode 没有添加Windows右键菜单
  • Java图形编程实战:从基础绘制到高级动画实现
  • 函数01 day10
  • 【PostgreSQL安装】保姆级安装教程+特性详解
  • 深入理解Go并发模型:从CSP理论到生产实践的完整指南
  • encodeURIComponent和decodeURIComponent
  • OpenHarmony按键分发流程(60%)
  • 安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
  • 云安全与网络安全:核心区别与协同作用解析
  • Android Jetpack Compose开发纯自定义表盘【可用于体重,温度计等项目】
  • 资讯网站的优势/安卓优化大师下载
  • 个体可以做企业网站吗/营销型网站制作公司
  • 中国开发网站的公司/网络整合营销方案ppt
  • 韶关网站建设制作/互联网推广员是做什么
  • python做网站效率/b2b免费网站推广平台
  • 帝国cms如何做电影网站/安卓优化大师下载安装到手机