STL 1 容器

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

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

文章目录

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 略慢。

相关推荐
门前云梦7 小时前
《C语言·源初法典》---C语言基础(上)
c语言·开发语言·学习
achene_ql7 小时前
select、poll、epoll 与 Reactor 模式
linux·服务器·网络·c++
sjtu_cjs8 小时前
Tensorrt python api 10.11.0笔记
开发语言·笔记·python
哆啦A梦的口袋呀8 小时前
深入理解系统:UML类图
开发语言·python·uml
虎冯河8 小时前
怎么让Comfyui导出的图像不包含工作流信息,
开发语言·python
coding随想8 小时前
JavaScript中的原始值包装类型:让基本类型也能“变身”对象
开发语言·javascript·ecmascript
SY师弟9 小时前
51单片机——计分器
c语言·c++·单片机·嵌入式硬件·51单片机·嵌入式
2301_794333919 小时前
Maven 概述、安装、配置、仓库、私服详解
java·开发语言·jvm·开源·maven
葬爱家族小阿杰9 小时前
python执行测试用例,allure报乱码且未成功生成报告
开发语言·python·测试用例