STL下常见容器底层数据结构

C++ 标准模板库(STL)中的容器根据其对内存的管理方式和数据组织形式,主要分为序列式容器(Sequence Containers)和关联式容器(Associative Containers),以及 C++11 引入的无序关联容器(Unordered Associative Containers)。

1. 序列式容器 (Sequence Containers)

1.std::vector (向量)

  • 底层结构动态数组 (Dynamic Array)
  • 特点
    • 内存连续分配,支持随机访问( O(1) )。
    • 尾部插入/删除效率高(均摊O(1) ),但中间或头部插入/删除效率低( O(n) ,因为需要移动元素)。
    • 当容量不足时,会重新分配一块更大的内存(通常是原来的 1.5 倍或 2 倍),并将旧数据拷贝过去,这可能导致迭代器失效。
  • 适用场景:需要频繁随机访问,且主要在尾部进行增删操作的场景。

2.std::deque (双端队列)

  • 底层结构分段连续空间(通常实现为"数组的数组"或"中控地图 + 缓冲区")。
  • 特点
    • 由一段段定长的连续空间组成,通过一个中控指针(map)来管理这些分段。
    • 支持首尾两端的高效插入和删除( O(1) )。
    • 支持随机访问( O(1) ),但比 vector 稍慢,因为涉及两次指针跳转(先找段,再找段内偏移)。
    • 内存不需要完全连续,扩容时只需分配新的分段,无需整体拷贝。
  • 适用场景:需要频繁在首尾两端进行增删操作,且需要随机访问的场景。

3.std::list (链表)

  • 底层结构双向链表 (Doubly Linked List)
  • 特点
    • 内存不连续,每个节点包含数据域、前驱指针和后继指针。
    • 不支持随机访问(访问第 n 个元素需 O(n) )。
    • 在任意位置插入和删除元素效率极高( O(1) ,前提是已知位置迭代器),因为只需修改指针,无需移动元素。
    • 额外内存开销较大(每个节点需存两个指针)。
  • 适用场景:需要频繁在任意位置进行插入/删除,且不常进行随机访问的场景。

4.std::forward_list (单向链表)

  • 底层结构单向链表 (Singly Linked List)
  • 特点
    • list 更节省空间(每个节点只有一个后继指针)。
    • 只能向前遍历,不支持反向迭代器。
    • 插入/删除操作同样高效,但某些操作(如 insert 之前)需要记录前驱节点,接口设计上略有不同。

5.std::array

  • 底层结构固定大小数组
  • 特点
    • 封装了原生数组,大小在编译期确定,不可改变。
    • 内存连续,零开销抽象。

2. 关联式容器 (Associative Containers)

这类容器通过键值(Key)来检索元素,内部通常采用平衡二叉树结构,元素自动排序。

  • std::set / std::multiset
  • std::map / std::multimap
    • 底层结构红黑树 (Red-Black Tree)
      • 红黑树是一种自平衡的二叉搜索树(BST)。
    • 特点
      • 所有操作(查找、插入、删除)的时间复杂度均为 O(logn) 。
      • 元素会根据 Key 自动排序(默认升序)。
      • map 存储 pair<const Key, Value>set 存储 Key
      • multi 版本允许键值重复。
      • 迭代器失效规则相对宽松:插入节点通常不会导致其他节点的迭代器失效(除了被删除的节点)。
    • 适用场景:需要元素有序,且对查找、插入、删除效率有稳定要求( O(logn) )的场景。

3. 无序关联容器 (Unordered Associative Containers)

C++11 引入,基于哈希表实现,不保证元素顺序,但平均效率更高。

  • std::unordered_set / std::unordered_multiset
  • std::unordered_map / std::unordered_multimap
    • 底层结构哈希表 (Hash Table)
      • 具体实现通常为:数组 + 链表 (拉链法,Chaining)或 数组 + 开放寻址法(Open Addressing)。
      • 主流实现(如 GCC)通常使用拉链法:一个桶数组(Bucket Array),每个桶指向一个链表(或红黑树,当链表过长时可能转为树以优化最坏情况,类似 Java HashMap),冲突的元素挂在链表上。
    • 特点
      • 平均查找、插入、删除时间复杂度为O(1) 。
      • 最坏情况下(哈希冲突严重)退化为 O(n) 。
      • 元素无序存储。
      • 需要用户自定义哈希函数(对于非基本类型)。
    • 适用场景:不需要元素有序,追求极致查找速度,且能接受最坏情况波动的场景。

4. 容器适配器 (Container Adapters)

它们不是独立的容器,而是基于上述容器封装而成的特定数据结构。

  • std::stack (栈)

    • 默认底层容器std::deque
    • 可选底层std::vectorstd::list
    • 特性:后进先出 (LIFO)。
  • std::queue (队列)

    • 默认底层容器std::deque
    • 可选底层std::list(不能用 vector,因为 vector 不支持高效的头部删除)。
    • 特性:先进先出 (FIFO)。
  • std::priority_queue (优先队列)

    • 默认底层容器std::vector
    • 数据结构逻辑堆 (Heap)(通常是大顶堆)。
    • 特性 :通过底层容器的 push_heappop_heap 算法维持堆性质,队头始终是最大(或最小)元素。

总结对比

容器 底层数据结构 随机访问 头部插入/删除 中间插入/删除 尾部插入/删除 查找复杂度 是否有序
vector 动态数组 O(1) O(n) O(n) O(1)* O(n)/O(logn)
deque 分段连续数组 O(1) O(1) O(n) O(1) O(n)
list 双向链表 不支持 O(1) O(1) O(1) O(n)
map/set 红黑树 不支持 O(log n) O(log n) O(log n) O(log n)
unordered_map/set 哈希表 不支持 - - - 平均O(1)

注:vector 尾部插入在扩容时为O(n) ,但均摊复杂度为O(1) 。

相关推荐
于先生吖1 小时前
基于 Java 开发短剧系统:完整架构与核心功能实现
java·开发语言·架构
老鱼说AI1 小时前
CUDA架构与高性能程序设计:多维网格与数据
c++·人工智能·深度学习·神经网络·机器学习·语言模型·cuda
badhope1 小时前
GitHub超有用项目推荐:skill仓库--用技能树打造AI超频引擎
java·开发语言·前端·人工智能·python·重构·github
海边的梦1 小时前
救命!此电脑网络位置异常?AD域排错3步封神,DNS/NetLogon/GPO根因一键定位
服务器·开发语言·php
时寒的笔记1 小时前
js逆向入门03_会展中心案例&shuwei观察&ji思录
开发语言·前端·javascript
逆境不可逃1 小时前
【后端新手谈 04】Spring 依赖注入所有方式 + 构造器注入成官方推荐的原因
java·开发语言·spring boot·后端·算法·spring·注入方式
英英_1 小时前
MATLAB MapReduce 从入门到实战:大数据处理完整教程
开发语言·matlab·mapreduce
Anastasiozzzz1 小时前
深度解析 Java 单例模式
java·开发语言
NGC_66111 小时前
G1收集器
java·开发语言·jvm