【数据结构】stl 容器

序列容器(顺序存储元素)

关联容器(基于键值存储,允许快速查找)

有序关联容器‌(元素按键排序):

无序关联容器‌(C++11引入,基于哈希表):

容器适配器(基于其他容器封装)

其他容器




std::vector 数据结构与内存管理

1. 底层结构
  • 连续内存块‌:元素在内存中紧密排列
  • 三指针逻辑 ‌(典型实现):
    • begin_ptr → 内存起始位置
    • size_ptr → 当前元素末尾(size()
    • capacity_ptr → 内存块末尾(capacity()

2. 插入操作
场景 操作步骤 时间复杂度
尾部空间充足 1. 在size_ptr处构造元素 2. size_ptr后移 O(1)
空间不足需扩容 1. 分配新内存(容量:GCC×2 / MSVC×1.5) 2. 迁移数据(优先移动语义) 3. 释放旧内存 均摊 O(1)
中间插入 1. 移动后续元素腾出空间 2. 构造新元素 O(n)

3. 删除操作
类型 操作步骤 时间复杂度
尾部删除 1. 销毁末尾元素 2. size_ptr前移 O(1)
中间删除 1. 销毁目标元素 2. 向前移动后续元素覆盖空隙 O(n)

4. 关键特性
  • 内存策略 ‌:

    • 扩容:指数增长(避免频繁重分配)

    • 不自动缩容:erase不释放内存

    • 手动释放:

      cpp 复制代码
      v.shrink_to_fit();      // 请求释放多余内存
      vector<int>().swap(v);  // 强制释放所有内存
  • 迭代器失效 ‌:

    • 扩容或中间插入/删除导致迭代器失效
  • 性能对比 ‌:

    操作 复杂度 适用性
    随机访问 O(1) ★★★★★
    尾部操作 均摊 O(1) ★★★★★
    中间操作 O(n) ★☆☆☆☆


std::deque 核心知识点总结

一、基础概念与特性
  1. 容器类型
    C++ STL 中的‌双端队列‌(double-ended queue)
  2. 访问特性
    支持‌随机访问 ‌(通过 operator[]at()
  3. 动态扩展
    两端插入/删除操作高效,时间复杂度为 ‌**O(1)**‌
  4. 底层实现
    基于‌分段连续存储‌结构(多个固定大小的数组块 + 中央控制块)

二、内存管理机制
特性 说明
默认分配器 std::allocator<T>
分段存储结构 由多个‌固定大小的数组块‌组成(典型块大小 512 bytes - 4KB)
中央控制映射器 维护指向所有块的指针数组(动态扩容时重新分配)
内存分配策略 插入时: - 两端:直接使用预留空间或分配新块 - 中间:移动元素
扩容机制 中央指针数组满时重新分配(通常翻倍)
非连续内存 元素物理存储非连续,但逻辑连续

内存布局示例‌:

复制代码
控制映射器: [ptr0, ptr1, ptr2, ...]
              |      |      |
块0: [a,b,c] 块1: [d,e,f] 块2: [g,h,i]

三、核心操作特性
操作 时间复杂度 说明
头尾插入/删除 O(1) push_front()/pop_front() push_back()/pop_back()
随机访问 O(1) operator[]at() 直接访问元素
中间插入/删除 O(n) insert()/erase() 需移动元素
迭代器操作 O(1) 支持随机访问迭代器(++, --, +n 等)

四、模板参数
cpp 复制代码
template<
    class T,                     // 元素类型
    class Allocator = std::allocator<T>  // 分配器类型
> class deque;


std::list 核心知识点总结

一、基础概念与特性
  1. 容器类型
    C++ STL 中的‌双向链表‌容器
  2. 存储结构
    每个元素存储在独立的节点中,节点包含:
    • 数据值
    • 前驱节点指针
    • 后继节点指针
  3. 迭代器特性
    支持‌双向迭代器‌(可前向/后向遍历)

二、内存管理机制
特性 说明
默认分配器 std::allocator<T>
节点内存分配 每个元素独立分配内存(包含数据+两个指针)
分配触发时机 push_back/push_front/insert 时分配新节点
内存释放时机 pop_back/pop_front/erase 时立即释放节点
内存碎片 高频插入删除可能产生内存碎片
连续内存 ❌ 元素在内存中‌非连续存储

节点结构示例‌:

cpp 复制代码
struct ListNode {
    T data;          // 存储的元素值
    ListNode* prev;  // 前驱节点指针
    ListNode* next;  // 后继节点指针
};

三、核心操作特性
操作 时间复杂度 说明
头尾插入/删除 O(1) push_front()/pop_front() push_back()/pop_back()
任意位置插入 O(1) insert(iterator_pos, value)(只需修改相邻节点指针)
任意位置删除 O(1) erase(iterator_pos)(只需修改相邻节点指针)
元素查找 O(n) 必须从头/尾开始遍历
迭代器稳定性 ✅ 稳定 插入/删除操作‌不会使其他迭代器失效‌(除被删除元素的迭代器)

四、特殊成员函数
  1. 链表拼接
    splice():将其他链表的元素移动到当前链表(O(1)时间复杂度)
    // 将other链表的全部元素移动到当前链表末尾
    mylist.splice(mylist.end(), otherlist);


std::forward_list 核心知识点总结

一、基础概念与特性
  1. 单向链表结构
    C++11 引入的‌单向链表‌容器,每个节点包含数据值和指向下一节点的指针
  2. 最小化内存开销
    相比 std::list 节省内存(每个节点少一个指针)
  3. 迭代器特性
    仅支持‌前向迭代器‌(不可反向遍历)

二、内存管理机制
特性 说明
默认分配器 std::allocator<T>
节点结构 { data, next_ptr }(仅含数据域和单向指针)
内存分配 插入操作时动态分配新节点(如 push_front, insert_after
内存释放 删除操作立即释放节点内存(如 pop_front, erase_after
内存碎片 高频插入删除可能产生碎片(但比 std::list 碎片少 25%)

节点结构示例‌:

cpp 复制代码
struct ForwardListNode {
    T data;          // 存储的元素值
    ForwardListNode* next;  // 指向下一节点的指针
};

三、核心操作特性
操作 时间复杂度 说明
头部插入 O(1) push_front() 在链表头插入新元素
指定位置后插入 O(1) insert_after(pos) 在迭代器 pos 后插入元素
头部删除 O(1) pop_front() 删除首元素
指定位置后删除 O(1) erase_after(pos) 删除 pos 后元素
元素查找 O(n) 必须从头节点开始顺序遍历
迭代器稳定性 ✅ 稳定 插入/删除操作‌不影响其他迭代器‌(除被删元素的迭代器)

四、特殊成员函数
  1. 首前迭代器
    before_begin():返回首元素前的虚拟节点迭代器(用于首元素操作)
    auto it = flist.before_begin();
    flist.insert_after(it, 42); // 在链表头插入


std::array 核心知识点总结

一、基础概念与特性
  1. 固定大小数组容器
    C++11 引入的‌静态连续数组‌容器,封装原生数组
  2. 内存分配方式
    元素在‌栈内存 ‌或‌全局/静态存储区‌分配(与原生数组相同)
  3. 零额外开销
    相比原生数组,不增加任何空间或时间开销(编译期确定大小)

二、模板参数与声明
cpp 复制代码
template<
    class T,         // 元素类型
    std::size_t N    // 数组固定大小
> class array;

关联容器(基于键值存储,允许快速查找)

‌有序关联容器‌(元素按键排序):



std::set 核心知识点总结

一、基础概念与特性
  1. 有序关联容器
    存储‌唯一键值‌(无重复元素)并自动按键排序
  2. 红黑树实现
    基于‌红黑树‌(自平衡二叉搜索树)实现,保证操作效率
  3. 自动排序机制
    元素始终‌按键升序排列 ‌(默认std::less<Key>

二、内存管理机制
特性 说明
默认分配器 std::allocator<Key>
节点内存分配 每个元素独立分配内存(含数据+父/子指针+颜色标志)
分配触发时机 insert() 操作时动态分配新节点
内存释放时机 erase() 操作时立即释放节点内存
内存布局 树形结构存储,节点间‌非连续内存

节点结构示例‌:

cpp 复制代码
struct Node {
    Node* parent;
    Node* left;
    Node* right;
    bool color;  // 红黑树颜色标志
    Key value;   // 存储的元素值
};

三、核心操作特性
操作 时间复杂度 说明
插入元素 O(log n) insert(key)emplace(args)
删除元素 O(log n) erase(key)erase(iterator)
查找元素 O(log n) find(key)/contains(key)(C++20)
范围查询 O(log n) lower_bound()/upper_bound() 实现高效范围扫描
迭代器稳定性 ✅ 稳定 插入/删除操作‌不影响其他迭代器‌(除被删元素的迭代器)

四、模板参数
cpp 复制代码
template<
    class Key,                   // 元素类型(必须支持严格弱序比较)
    class Compare = std::less<Key>, // 比较器(默认升序)
    class Allocator = std::allocator<Key> // 内存分配器
> class set;


std::multiset 核心知识点总结

一、基础概念与特性
  1. 有序关联容器
    存储‌可重复键值 ‌的集合,元素自动按键排序
    set是多了判断是否重复
  2. 红黑树实现
    基于‌红黑树‌(自平衡二叉搜索树)实现
  3. 自动排序机制
    元素始终‌按键升序排列 ‌(默认std::less<Key>

二、内存管理机制
特性 说明
默认分配器 std::allocator<Key>
节点结构 每个节点包含: - 键值数据 - 父/子节点指针 - 红黑树颜色标志
内存分配 insert() 操作时动态分配新节点
内存释放 erase() 操作时立即释放节点内存
内存布局 树形结构存储,节点间‌非连续内存
内存占用 每个节点额外开销约 3 指针 + 1 bool(通常 16-32 字节)

节点结构示例‌:

cpp 复制代码
struct Node {
    Node* parent;   // 父节点指针
    Node* left;     // 左子节点指针
    Node* right;    // 右子节点指针
    bool color;     // 红黑树颜色标志
    Key value;      // 存储的元素值
};

三、核心操作特性
操作 时间复杂度 说明
插入元素 O(log n) insert(key) 可重复插入相同键值
删除元素 O(log n) erase(key) 删除所有匹配键值;erase(iterator) 删除指定元素
元素计数 O(log n) count(key) 返回匹配键值的元素数量
范围查询 O(log n) equal_range(key) 获取相同键值元素的范围迭代器对
迭代器稳定性 ✅ 稳定 插入/删除操作‌不影响其他迭代器

四、模板参数
cpp 复制代码
template<
    class Key,                   // 元素类型(必须支持严格弱序比较)
    class Compare = std::less<Key>, // 比较器(默认升序)
    class Allocator = std::allocator<Key> // 内存分配器
> class multiset;


std::map 核心知识点总结

一、基础概念与特性

  1. 容器类型
    C++ STL 中的‌有序关联容器 ‌,存储键值对(key-value pairs
  2. 排序特性
    元素始终‌按键(key)自动排序‌(默认升序)
  3. 键唯一性
    每个键在 std::map 中‌唯一‌(不允许重复键)
  4. 底层实现
    基于‌红黑树‌(自平衡二叉搜索树)实现,保证操作效率

二、内存管理机制

特性 说明
默认分配器 std::allocator<std::pair<const Key, T>>
内存分配方式 动态分配(堆内存),每个节点独立分配
分配触发时机 插入新元素时为键值对分配内存;删除时释放对应内存
内存布局 树形结构存储,每个节点包含:父/子指针、颜色标志、键值对数据
连续内存 ❌ 元素在内存中‌非连续存储‌,迭代器遍历可能产生缓存未命中

示例节点结构(简化):

cpp 复制代码
struct Node {
    Node* parent;
    Node* left;
    Node* right;
    bool color;  // 红黑树颜色标志
    std::pair<const Key, T> data;  // 键值对
};

三、核心操作特性

操作 时间复杂度 说明
插入 O(log n) insert()emplace() 添加新元素
查找 O(log n) find()/count()/contains()(C++20)
删除 O(log n) erase() 移除指定键或迭代器位置元素
访问 O(log n) operator[] 访问或创建元素;at() 边界检查访问
范围查询 O(log n) lower_bound()/upper_bound() 实现高效范围扫描

四、模板参数与自定义

cpp 复制代码
template<
    class Key,                   // 键类型(必须支持严格弱序比较)
    class T,                     // 值类型
    class Compare = std::less<Key>, // 比较器(默认升序)
    class Allocator = std::allocator<std::pair<const Key, T>> // 内存分配器
> class map;


std::multimap 核心知识点总结

一、基础概念与特性
  1. 有序关联容器
    存储‌可重复键值对‌(允许相同键对应多个值)
  2. 红黑树实现
    基于‌红黑树‌(自平衡二叉搜索树)实现
  3. 自动排序机制
    元素始终‌按键升序排列 ‌(默认std::less<Key>

二、内存管理机制
特性 说明
默认分配器 std::allocator<std::pair<const Key, T>>
节点结构 每个节点包含: - 键值对数据 - 父/子节点指针 - 红黑树颜色标志
内存分配 insert() 操作时动态分配新节点
内存释放 erase() 操作时立即释放节点内存
内存布局 树形结构存储,节点间‌非连续内存

节点结构示例‌:

cpp 复制代码
struct Node {
    Node* parent;   // 父节点指针
    Node* left;     // 左子节点指针
    Node* right;    // 右子节点指针
    bool color;     // 红黑树颜色标志
    std::pair<const Key, T> data;  // 键值对
};

三、与 std::map 的关键区别
特性 std::multimap std::map
键唯一性 ❌ 允许重复键 ✅ 键必须唯一
插入行为 总是成功(不覆盖) 键存在时插入失败或覆盖值
operator[] ❌ 不支持 ✅ 支持(自动创建键)
查找返回值 返回匹配键的范围迭代器 返回单个元素迭代器
典型应用场景 一对多关系(如电话簿同名条目) 键值唯一映射(如ID映射)

四、核心操作特性
操作 时间复杂度 说明
插入元素 O(log n) insert({key, value}) 可重复插入相同键值对
删除元素 O(log n) erase(key) 删除所有匹配键值;erase(iterator) 删除指定元素
键值查找 O(log n) find(key) 返回首个匹配键值的迭代器
范围查询 O(log n) equal_range(key) 获取相同键值的迭代器范围
元素计数 O(log n) count(key) 返回匹配键值的元素数量

五、特殊成员函数
  1. 键值范围访问
    equal_range(key):获取相同键值的迭代器范围
    auto [first, last] = phonebook.equal_range("Alice");
    for (auto it = first; it != last; ++it)
    std::cout << it->second; // 输出所有Alice的电话


std::unordered_set 核心知识点总结

一、基础概念与特性
  1. 无序关联容器
    C++11 引入的‌哈希集合 ‌,存储‌唯一键值 ‌(无重复元素)
    相比unordered_map 仅存key 且不支持【】访问
  2. 哈希表实现
    基于‌哈希表‌(链地址法或开放寻址法)实现
  3. 无序存储
    元素存储顺序‌不固定‌,取决于哈希函数和桶分布

二、内存管理机制
特性 说明
默认分配器 std::allocator<Key>
桶数组结构 维护‌动态数组‌存储桶指针(桶即链表头节点或开放寻址槽位)
节点内存分配 插入时动态分配节点(含键值 + 链表指针)
扩容机制 当负载因子(元素数/桶数)超过阈值(默认 1.0)时: 1. 桶数组翻倍扩容 2. 所有元素‌重新哈希‌到新桶
内存释放 erase() 立即释放节点内存;桶数组在对象销毁时释放

典型节点结构‌(链地址法):

cpp 复制代码
struct Node {
    Key value;      // 存储的元素值
    Node* next;     // 下一节点指针
};

三、核心操作特性
操作 平均复杂度 最坏复杂度 说明
插入元素 O(1) O(n) insert(key)emplace(args)
删除元素 O(1) O(n) erase(key)erase(iterator)
查找元素 O(1) O(n) find(key)/contains(key)(C++20)
迭代器稳定性 ❌ 不稳定 - 扩容操作使‌所有迭代器失效

四、模板参数
cpp 复制代码
template<
    class Key,                     // 键类型
    class Hash = std::hash<Key>,   // 哈希函数对象
    class KeyEqual = std::equal_to<Key>, // 键相等比较器
    class Allocator = std::allocator<Key> // 分配器
> class unordered_set;


std::unordered_multiset 核心知识点总结

一、基础概念与特性
  1. 无序关联容器
    存储‌可重复键值‌的集合,元素顺序由哈希函数决定
  2. 哈希表实现
    基于‌链式哈希表‌实现(数组 + 链表冲突解决)
  3. 快速查找特性
    平均时间复杂度 O(1),最坏情况 O(n)

二、内存管理机制
特性 说明
默认分配器 std::allocator<Key>
桶数组结构 动态数组存储桶指针(初始大小由实现定义)
节点内存分配 每个元素独立分配节点(含键值 + 链表指针)
动态扩容 当负载因子 (元素数/桶数) > max_load_factor()(默认1.0)时: - 桶数组扩容(通常翻倍) - 重新哈希所有元素
内存释放 erase() 立即释放节点内存;桶数组在对象销毁时释放

节点结构‌:

cpp 复制代码
struct Node {
    Key value;      // 存储的元素值
    Node* next;     // 下一节点指针
};

三、核心操作特性
操作 平均复杂度 最坏复杂度 说明
插入元素 O(1) O(n) insert(key) 允许重复插入相同键值
删除元素 O(1) O(n) erase(key) 删除所有匹配键值;erase(iterator) 删除指定元素
元素计数 O(n) O(n) count(key) 返回匹配键值的元素数量
范围查询 O(n) O(n) equal_range(key) 获取相同键值元素的范围迭代器对

四、模板参数
cpp 复制代码
template<
    class Key,                     // 键类型
    class Hash = std::hash<Key>,   // 哈希函数对象
    class KeyEqual = std::equal_to<Key>, // 键相等比较器
    class Allocator = std::allocator<Key> // 分配器
> class unordered_multiset;

std::unordered_map:哈希实现的键值对映射(键唯一)

哈希表核心知识点总结

一、基础结构
  1. 数组槽位
    • 哈希表的第一维是数组结构,称为"槽"(slots)或"桶"(buckets)
    • 每个槽存储键值对或冲突处理结构(链表/树的头节点)
二、容量机制
  1. 初始容量

    • 创建时指定(如 Java HashMap 默认 16,Go map 默认 8)
    • 未指定时采用语言/库默认值
  2. 动态扩容

    • 触发条件:元素数量 > 当前容量 × 负载因子(通常 0.5-0.75)
    • 扩容策略:
      • 倍增策略‌:容量翻倍(如 16 → 32),保持 2 的幂
      • 质数策略‌:取大于 2 倍容量的最小质数
    • 扩容后需‌重新哈希‌所有元素
三、内存分配机制
场景 内存分配行为
首次初始化 ✅ 分配初始数组内存
触发扩容时 ✅ 分配新数组内存
链表法插入新键 ✅ 分配节点内存
开放寻址法插入新键 ❌ 使用预分配槽位
更新已存在键的值 ❌ 不分配新内存
四、冲突处理策略
  1. 链表法

    • 每个槽位维护链表结构存储冲突元素
    • 插入新键必分配节点内存
  2. 开放寻址法

    • 所有元素直接存储在数组槽位中
    • 通过线性探测/二次探测解决冲突
    • 插入新键通常不分配额外内存


std::unordered_multimap 核心知识点总结

一、基础概念与特性
  1. 无序关联容器
    C++11 引入的‌哈希键值对容器 ‌,允许‌重复键值‌(同键可对应多个值)
  2. 哈希表实现
    基于‌链式哈希表‌实现(数组 + 链表冲突解决)
  3. 无序存储特性
    元素顺序由‌哈希函数‌决定,遍历时无固定顺序

二、内存管理机制
特性 说明
默认分配器 std::allocator<std::pair<const Key, T>>
桶数组结构 动态数组存储桶指针(初始大小由实现定义)
节点内存分配 插入时动态分配节点(含键值对 + 链表指针)
动态扩容 当负载因子 (元素数/桶数) > max_load_factor()(默认1.0)时: 1. 桶数组扩容(通常翻倍) 2. 所有元素‌重新哈希‌到新桶
内存释放 erase() 立即释放节点内存;桶数组在对象销毁时释放

节点结构‌:

cpp 复制代码
struct Node {
    std::pair<const Key, T> data;  // 键值对
    Node* next;                     // 下一节点指针
};

三、核心操作特性
操作 平均复杂度 最坏复杂度 说明
插入元素 O(1) O(n) insert({key, value}) 允许重复键值对插入
删除元素 O(1) O(n) erase(key) 删除所有匹配键值;erase(iterator) 删除指定元素
键值查找 O(1) O(n) find(key) 返回首个匹配键值的迭代器
范围查询 O(1) O(n) equal_range(key) 获取相同键值的迭代器范围
迭代器稳定性 ❌ 不稳定 - 扩容操作使‌所有迭代器失效

四、模板参数
cpp 复制代码
template<
    class Key,                     // 键类型
    class T,                       // 值类型
    class Hash = std::hash<Key>,   // 哈希函数对象
    class KeyEqual = std::equal_to<Key>, // 键相等比较器
    class Allocator = std::allocator<std::pair<const Key, T>> // 分配器
> class unordered_multimap;

容器适配器(基于其他容器封装)

std::stack 核心知识点总结

一、基础概念与特性
  1. 容器适配器
    C++ STL 中的‌栈结构容器适配器‌,提供后进先出(LIFO)操作接口
  2. 底层容器依赖
    基于其他序列容器实现(默认使用 std::deque
  3. 受限访问
    仅允许在栈顶进行插入和删除操作

二、内存管理机制
特性 说明
底层容器决定内存 内存管理完全由底层容器(如 std::deque)负责
默认底层容器 std::deque(分段连续存储,动态扩容)
内存分配行为 遵循底层容器的分配策略: - push() 可能触发扩容 - pop() 释放元素内存
无独立内存管理 作为适配器不直接管理内存,完全依赖底层容器实现

当使用默认 std::deque 时:

  • 内存分段存储在固定大小块中
  • 动态扩容时分配新内存块
  • 不释放已分配的内存块直到对象销毁

三、核心操作接口
操作 时间复杂度 说明
入栈 O(1) push(value) 在栈顶插入元素
出栈 O(1) pop() 移除栈顶元素(不返回值)
访问栈顶 O(1) top() 返回栈顶元素引用(空栈调用导致未定义行为)
容量查询 O(1) size() 返回元素数量 empty() 判断是否为空

四、模板参数与自定义
cpp 复制代码
template<
    class T,                           // 元素类型
    class Container = std::deque<T>    // 底层容器类型
> class stack;


std::queue 核心知识点总结

一、基础概念与特性
  1. 容器适配器
    C++ STL 中的‌队列结构容器适配器‌,提供先进先出(FIFO)操作接口
  2. 底层容器依赖
    基于其他序列容器实现(默认使用 std::deque
  3. 受限访问
    仅允许在队尾插入元素,队头删除元素

二、内存管理机制
特性 说明
底层容器决定内存 内存管理完全由底层容器(如 std::deque)负责
默认底层容器 std::deque(分段连续存储,动态扩容)
内存分配行为 遵循底层容器的分配策略: - push() 可能触发扩容 - pop() 释放元素内存
无独立内存管理 作为适配器不直接管理内存,完全依赖底层容器实现

当使用默认 std::deque 时:

  • 内存分段存储在固定大小块中
  • 动态扩容时分配新内存块
  • 不释放已分配的内存块直到对象销毁

三、核心操作接口
操作 时间复杂度 说明
入队 O(1) push(value) 在队尾插入元素
出队 O(1) pop() 移除队头元素(不返回值)
访问队头 O(1) front() 返回队头元素引用(空队列调用导致未定义行为)
访问队尾 O(1) back() 返回队尾元素引用
容量查询 O(1) size() 返回元素数量 empty() 判断是否为空

四、模板参数与自定义
cpp 复制代码
template<
    class T,                           // 元素类型
    class Container = std::deque<T>    // 底层容器类型
> class queue;


std::priority_queue 核心知识点总结

一、基础概念与特性
  1. 容器适配器
    C++ STL 中的‌优先级队列‌容器适配器,提供基于优先级的元素访问
  2. 堆结构实现
    底层实现为‌二叉堆‌数据结构(默认最大堆)
  3. 访问特性
    • 仅能访问堆顶元素(优先级最高元素)
    • 不支持随机访问或迭代器遍历

二、内存管理机制
特性 说明
底层容器决定内存 内存管理由底层容器(默认 std::vector)负责
堆结构特性 元素以‌完全二叉树‌形式存储,满足堆序性质
内存分配行为 遵循底层容器的分配策略: - push() 可能触发扩容 - pop() 释放元素内存
默认容器 std::vector(连续内存存储,支持高效随机访问)
扩容机制 当底层 vector 容量不足时: 1. 分配新内存 2. 迁移元素并重建堆

内存布局示例‌(最大堆):

复制代码
       30
      /  \
     20  15
    / \
   10  5
对应vector: [30, 20, 15, 10, 5]

三、核心操作接口
操作 时间复杂度 说明
插入元素 O(log n) push(value) 插入元素并调整堆结构
删除堆顶 O(log n) pop() 移除堆顶元素并调整堆结构
访问堆顶 O(1) top() 返回堆顶元素引用(空队列调用导致未定义行为)
容量查询 O(1) size() 返回元素数量 empty() 判断是否为空

四、模板参数与自定义
cpp 复制代码
template<
    class T,                              // 元素类型
    class Container = std::vector<T>,     // 底层容器
    class Compare = std::less<typename Container::value_type> // 比较器
> class priority_queue;


std::bitset 核心知识点总结

一、基础概念与特性
  1. 固定大小位集合
    C++ STL 提供的‌固定长度位数组‌容器,用于高效处理二进制标志位
  2. 编译时确定大小
    大小 N 在编译时指定,无法运行时动态改变
  3. 内存高效存储
    每个位仅占 1 bit 空间,无额外内存开销

二、内存管理机制
特性 说明
内存分配位置 栈内存(或作为成员变量时随对象分配)
内存布局 连续内存块存储,按机器字长(word)分组
内存计算 总内存 = ceil(N / (sizeof(WordType) * CHAR_BIT)) * sizeof(WordType)
无动态内存 不涉及堆内存分配,无析构释放操作

示例 ‌:
std::bitset<64> 在 64 位系统占用 8 字节(64/8=1 word)
std::bitset<65> 在 64 位系统占用 16 字节(65/64≈2 words)


三、核心操作接口
操作 说明
位访问 operator[] 访问特定位;test(pos) 带边界检查访问
位设置 set(pos) 置位;reset(pos) 清零;flip(pos) 翻转
批量操作 set() 全置位;reset() 全清零;flip() 全翻转
位运算 支持 &, `
转换操作 to_ulong()/to_ullong() 转整数;to_string() 转二进制字符串

四、特殊功能
  1. 位统计
    count() 返回置位(1)的数量

    cpp 复制代码
    std::bitset<8> bs(0b10101010);
    bs.count();  // 返回 4

`std::valarray

概述

std::valarray 是 C++ 标准库中的一个类模板,用于表示和操作数值数组,支持元素级数学运算和各种下标访问方式。它旨在优化数值计算,避免别名问题,并允许编译器进行循环融合等优化。

关键点

  • 设计目的:专为高效数值数组操作设计,支持元素级运算、切片和间接访问,但不提供标准迭代器(如 vector)。
  • 优化特性:操作可能返回代理对象以减少临时对象,支持并行化和循环优化,但实际实现中优化程度有限。
  • 内存管理:元素连续存储在动态分配的数组中,默认构造函数不分配内存,其他构造函数根据大小分配;resize 可改变大小,可能导致重新分配。
  • 限制:模板参数 T 需为数值类型(如算术类型或 std::complex);不支持自定义分配器。
  • 争议与使用:虽标准但使用较少,常被 vector 或其他库取代;研究表明其性能优化在现代编译器中未充分实现,但适合简单数值任务。

基本用法

std::valarray 的实例化如 std::valarray<double> va(5);,创建大小为 5 的数组,所有元素默认初始化。支持如 va += 2.0; 的元素级运算,返回新 valarray 或修改原对象。

优势与注意事项

优势在于内置数学函数(如 sum、min)和运算符重载,便于数值代码编写。注意:resize 会使指针/引用失效;操作假设无别名以优化,但需小心使用。



std::valarray 详细说明

引言

std::valarray 是 C++ 标准库(头文件 <valarray>)中的类模板,用于表示数值数组并支持高效的元素级数学操作。它允许元素 wise 的算术运算、逻辑运算和各种下标操作,包括切片(slice)和间接访问(indirect)。 该类设计时考虑了无别名假设,类似于 C 语言的 restrict 关键字,从而允许编译器优化,如循环融合。 表达式如 v1 = a * v2 + v3; 可被优化为单次循环遍历。一些实现(如 GNU libstdc++ 和 LLVM libc++)内部使用表达式模板,但进一步优化较少见。 valarray 适合数值计算,但实际使用中常被 std::vector 或第三方库(如 Eigen)替代,因为其优化潜力在现代编译器中未完全实现。

valarray 的模板参数 T 必须满足 NumericType 要求,通常为算术类型、指针或类似 std::complex 的类。 它不支持标准容器接口(如迭代器),但 C++11 引入了 std::begin 和 std::end 的重载。

成员类型
  • value_type:T,即存储元素的类型。
构造函数

std::valarray 提供多种构造函数,用于创建空数组或初始化数组:

  • 默认构造函数valarray(),创建空数组(大小 0),不分配内存。
  • 大小指定valarray(size_t count),分配 count 个元素,每个元素值初始化(默认构造)。
  • 值初始化valarray(const T& val, size_t count),分配 count 个元素,每个拷贝自 val。
  • 数组拷贝valarray(const T* ptr, size_t count),从 ptr 指向的数组拷贝 count 个元素。
  • 初始化列表 (C++11):valarray(initializer_list<T> ilist),从列表初始化,大小为列表长度。
  • 拷贝/移动构造函数valarray(const valarray&)valarray(valarray&&),分配与源相同大小的存储,并拷贝/移动元素。

析构函数 ~valarray() 释放内部存储。

成员函数

成员函数包括赋值、访问、运算和聚合操作:

  • 赋值operator=,赋值内容,可能导致重新分配。
  • 访问operator[],返回元素引用、切片(slice_array)或掩码子数组(mask_array)。
  • 一元运算符operator+operator-operator~operator!,对每个元素应用,返回新 valarray。
  • 复合赋值operator+= 等,对每个元素应用,返回 *this。
  • 交换swap,常数时间交换内容,不失效引用。
  • 大小size,返回元素数。
  • 调整大小resize(size_t new_size)resize(size_t new_size, const T& val),改变大小;若增大,新增元素默认/值初始化;若缩小,销毁多余元素;失效指针/引用。
  • 聚合summinmax,计算总和、最小/最大值。
  • 移位shift(零填充移位)、cshift(循环移位)。
  • 应用函数apply,对每个元素应用指定函数,返回新 valarray。
非成员函数
  • 交换 (C++11):std::swap(std::valarray)
  • 迭代器 (C++11):std::beginstd::end,返回指向开始/结束的指针。
  • 二元运算符operator+ 等,元素级应用,返回新 valarray。
  • 比较运算符operator== 等,元素级比较,返回 bool valarray。
  • 数学函数absexplogpowsqrtsincos 等,元素级应用,返回新 valarray。
运算符
  • 一元:成员函数形式,对元素应用。
  • 复合赋值:成员函数,修改自身。
  • 二元:非成员,元素级运算,支持 valarray 与 valarray 或 scalar。
  • 比较:非成员,返回 bool valarray。
内存分配与管理

std::valarray 的元素存储在连续的动态分配数组中,类似于 std::vector 但无完整迭代器支持。 默认构造函数不分配内存。 其他构造函数根据指定大小在堆上分配连续块,并初始化元素。 resize 操作可能导致重新分配:若新大小大于当前,分配更多空间并初始化新增元素;若小于,销毁多余元素并可能释放内存。 实现可能使用 copy-on-write 或 copy-on-reference 优化以减少拷贝。 无自定义分配器支持;resize 或赋值失效所有指针/引用。 一些实现(如 Microsoft)提供非标准 free() 以释放存储。

辅助类与高级特性
  • 切片与子数组 :使用 std::slicestd::gsliceslice_arraygslice_arraymask_arrayindirect_array 支持子集操作。
  • 模板参数推导(C++17):支持从初始化列表等推导 T。
  • 并行化潜力:设计允许操作并行执行,但依赖实现。
示例
cpp 复制代码
#include <valarray>
#include <iostream>

int main() {
    std::valarray<int> va = {1, 2, 3, 4};
    va += 5;  // 元素级加法: {6,7,8,9}
    std::cout << va.sum() << std::endl;  // 输出 30
    va.resize(2);  // 变为 {6,7}
    return 0;
}

此示例展示基本运算和 resize。

表格:常见成员函数总结
函数 描述 返回类型 注意事项
size 返回元素数 size_t 常量时间
resize 改变大小 void 可能失效引用
sum 元素总和 T 假设 T 支持 +
min/max 最小/最大 T 假设 T 支持 <
apply 应用函数 valarray 返回新数组
shift/cshift 移位 valarray shift 零填充,cshift 循环
swap 交换 void 常数时间,不失效引用
表格:运算符支持
类型 示例 行为
一元 +va, -va 新 valarray,元素应用
二元 va1 + va2 新 valarray,元素级
复合 va += scalar 修改 va
比较 va1 == va2 bool valarray,元素级
数学 std::sin(va) 新 valarray,元素应用
相关推荐
毕设源码-邱学长27 分钟前
【开题答辩全过程】以 基于PHP的发热病人管理平台的设计与实现为例,包含答辩的问题和答案
开发语言·php
Trouvaille ~27 分钟前
【Linux】UDP Socket编程实战(一):Echo Server从零到一
linux·运维·服务器·网络·c++·websocket·udp
HellowAmy30 分钟前
我的C++规范 - 线程池
开发语言·c++·代码规范
独自破碎E33 分钟前
【BISHI9】田忌赛马
android·java·开发语言
czy878747533 分钟前
const 在 C/C++ 中的全面用法(C/C++ 差异+核心场景+实战示例)
c语言·开发语言·c++
十五年专注C++开发33 分钟前
MinHook:Windows 平台下轻量级、高性能的钩子库
c++·windows·钩子技术·minhook
范纹杉想快点毕业39 分钟前
实战级ZYNQ中断状态机FIFO设计
java·开发语言·驱动开发·设计模式·架构·mfc
一只小小的芙厨1 小时前
寒假集训笔记·树上背包
c++·笔记·算法·动态规划
马猴烧酒.2 小时前
【面试八股|Java集合】Java集合常考面试题详解
java·开发语言·python·面试·八股
以卿a2 小时前
C++(继承)
开发语言·c++·算法