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

C++ 容器库概述:序列容器、关联容器与无序关联容器的原理、性能与应用

        C++ 标准库提供了多种容器,用于存储和管理数据集合。容器分为三大类:序列容器关联容器无序关联容器。每类容器有不同的特性和适用场景,下面从时间复杂度、空间复杂度和作用三个方面进行详细讲解,并附代码示例:


一、序列容器(Sequence Containers)

        序列容器按线性顺序存储元素,允许指定插入位置。共有 6 种标准序列容器(严格分类),但若包括容器适配器(如 stack 和 queue),则可能达到 8 种。

1. vector(动态数组)

  • 作用:动态数组,支持快速随机访问。

  • 时间复杂度

    • 尾部插入/删除:均摊 O(1)

    • 中间插入/删除:O(n)

    • 随机访问:O(1)

  • 空间复杂度:连续内存,预分配空间。

  • 示例

    #include <vector>
    std::vector<int> v = {1, 2, 3};
    v.push_back(4);       // 尾部插入
    int val = v[2];       // 随机访问

2. deque(双端队列)

  • 作用:双端队列,支持头尾快速插入。

  • 时间复杂度

    • 头尾插入/删除:O(1)

    • 中间插入/删除:O(n)

    • 随机访问:O(1)

  • 空间复杂度:分块存储,内存非连续。

  • 示例

    #include <deque>
    std::deque<int> d = {2, 3};
    d.push_front(1);      // 头部插入
    d.push_back(4);       // 尾部插入

3. list(双链表)

  • 作用:双向链表,支持任意位置快速插入。

  • 时间复杂度

    • 插入/删除:O(1)

    • 随机访问:O(n)

  • 空间复杂度:每个元素含前后指针。

  • 示例

    #include <list>
    std::list<int> l = {1, 3};
    auto it = l.begin();
    it++;
    l.insert(it, 2);     // 在第二个位置插入

4. forward_list(单链表)

  • 作用:单向链表,更节省内存。

  • 时间复杂度

    • 插入/删除:O(1)

    • 随机访问:O(n)

  • 空间复杂度:每个元素含单个指针。

  • 示例

    #include <forward_list>
    std::forward_list<int> fl = {2, 3};
    fl.push_front(1);     // 只能头部插入

5. array(静态数组)

  • 作用:固定大小数组,替代原生数组。

  • 时间复杂度

    • 插入/删除:不支持

    • 随机访问:O(1)

  • 空间复杂度:栈或静态内存分配。

  • 示例

    #include <array>
    std::array<int, 3> arr = {1, 2, 3};
    int val = arr.at(1);  // 安全访问

6. string(字符串动态数组)

  • 作用:专为字符串设计的动态数组。

  • 特性:类似 vector<char>,但支持字符串操作。

  • 示例

    #include <string>
    std::string s = "Hello";
    s += " World!";

二、容器适配器(Container Adapters)

容器适配器是对标准容器的封装,提供特定的接口和行为。使用序列容器,可以实现容器适配器。

栈(stack

1. 时间复杂度

  • 插入(pushO(1)

    • 在栈顶插入元素,直接添加到容器尾部。

  • 删除(popO(1)

    • 从栈顶删除元素,直接移除容器尾部元素。

  • 访问栈顶(topO(1)

    • 直接访问容器尾部元素。

2. 空间复杂度

  • 空间占用O(n)

    • 栈的空间占用取决于存储的元素数量。

  • 底层容器:默认使用 deque,也可以使用 vector 或 list

3. 适用场景

  • 需要后进先出(LIFO)行为的场景,如:

    • 函数调用栈(递归)。

    • 表达式求值(如括号匹配)。

    • 撤销操作(如编辑器中的撤销功能)。

4. 代码示例

#include <stack>
std::stack<int> s;
s.push(1);  // O(1)
s.push(2);  // O(1)
std::cout << s.top(); // 输出 2, O(1)
s.pop();    // O(1)
std::cout << s.top(); // 输出 1, O(1)

队列(queue

1. 时间复杂度

  • 插入(pushO(1)

    • 在队尾插入元素,直接添加到容器尾部。

  • 删除(popO(1)

    • 从队首删除元素,直接移除容器头部元素。

  • 访问队首(frontO(1)

    • 直接访问容器头部元素。

2. 空间复杂度

  • 空间占用O(n)

    • 队列的空间占用取决于存储的元素数量。

  • 底层容器:默认使用 deque,也可以使用 list

3. 适用场景

  • 需要先进先出(FIFO)行为的场景,如:

    • 任务调度(如打印任务队列)。

    • 消息队列(如事件处理系统)。

    • 广度优先搜索(BFS)算法。

4. 代码示例

#include <queue>
std::queue<int> q;
q.push(1);  // O(1)
q.push(2);  // O(1)
std::cout << q.front(); // 输出 1, O(1)
q.pop();    // O(1)
std::cout << q.front(); // 输出 2, O(1)

优先队列(priority_queue

1. 时间复杂度

  • 插入(pushO(log n)

    • 插入元素并调整堆结构。

  • 删除(popO(log n)

    • 删除堆顶元素并调整堆结构。

  • 访问堆顶(topO(1)

    • 直接访问堆顶元素。

2. 空间复杂度

  • 空间占用O(n)

    • 优先队列的空间占用取决于存储的元素数量。

  • 底层容器:默认使用 vector,也可以使用 deque

3. 适用场景

  • 需要动态获取最大或最小元素的场景,如:

    • 任务调度(按优先级处理任务)。

    • 最小生成树算法(如 Prim 算法)。

    • 最短路径算法(如 Dijkstra 算法)。

4. 代码示例

#include <queue>
std::priority_queue<int> pq;
pq.push(3);  // O(log n)
pq.push(1);  // O(log n)
pq.push(4);  // O(log n)
std::cout << pq.top(); // 输出 4, O(1)
pq.pop();    // O(log n)
std::cout << pq.top(); // 输出 3, O(1)

总结对比

容器适配器插入时间复杂度删除时间复杂度访问时间复杂度空间复杂度底层容器适用场景
栈 (stack)O(1)O(1)O(1)O(n)deque后进先出(LIFO)场景
队列 (queue)O(1)O(1)O(1)O(n)deque先进先出(FIFO)场景
优先队列 (priority_queue)O(log n)O(log n)O(1)O(n)vector动态获取最大/最小元素场景

三、关联容器(Associative Containers)

关联容器基于红黑树实现,元素按键有序存储,共有 4 种

1. set

  • 作用:有序唯一键集合。

  • 时间复杂度:插入/删除/查找 O(log n)

  • 示例

    #include <set>
    std::set<int> s = {3, 1, 2};
    s.insert(4);
    bool exists = s.count(2); // 返回 1

2. map

  • 作用:键值对集合,键唯一。

  • 时间复杂度O(log n)

  • 示例

    #include <map>
    std::map<std::string, int> m;
    m["apple"] = 5;
    m.insert({"banana", 3});

3. multiset

  • 作用:允许重复键的有序集合。

  • 示例

    std::multiset<int> ms = {1, 1, 2};
    ms.insert(1);

4. multimap

  • 作用:允许重复键的键值对集合。

  • 示例

    std::multimap<std::string, int> mm;
    mm.insert({"apple", 1});
    mm.insert({"apple", 2});

四、无序关联容器(Unordered Associative Containers)

无序容器基于哈希表实现,元素无序,共有 4 种

1. unordered_set

  • 作用:唯一键的无序集合。

  • 时间复杂度:平均 O(1),最坏 O(n)

  • 示例

    #include <unordered_set>
    std::unordered_set<int> us = {3, 1, 2};
    us.insert(4);

2. unordered_map

  • 作用:键值对的无序集合。

  • 示例

    #include <unordered_map>
    std::unordered_map<std::string, int> um;
    um["apple"] = 5;
    um["banana"] = 3;

3. unordered_multiset 和 unordered_multimap

  • 作用:允许重复键的无序集合/映射。

  • 示例

    std::unordered_multiset<int> ums = {1, 1, 2};
    std::unordered_multimap<std::string, int> umm;
    umm.insert({"apple", 1});
    umm.insert({"apple", 2});

总结

  • 序列容器:适用于需要保留插入顺序的场景(如 vector 用于快速随机访问,list 用于频繁插入)。

  • 关联容器:适用于需要有序遍历的场景(如按顺序处理数据)。

  • 无序关联容器:适用于快速查找且不关心顺序的场景(如缓存、字典)。

相关文章:

  • Docker Compose 使用笔记
  • QT 学习一 paintEvent,QPainter ,QImage
  • 智慧城市运行管理服务平台建设方案
  • STM32串口通信
  • ‘java‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。
  • 【网络】什么是 IHL(Internet Header Length,首部长度)TTL(Time To Live,生存时间)?
  • 【编解码技术】什么是编码复杂度?
  • SpringMVC(三)响应处理
  • 构建智能汽车地图标准体系:自动驾驶技术的基石
  • 一文讲清楚CUDA与PyTorch、GPU之间的关系
  • 基于Python的selenium入门超详细教程(第1章)--WebDriver API篇
  • 【Linux-传输层协议TCP】TCP协议段格式+确认应答+超时重传+连接管理机制(三次握手、四次挥手、理解TIME_WAIT + CLOSE_WAIT)
  • 结构型——适配器模式
  • 二维数组常见应用场景以及示例
  • [Ai 力扣题单] 数组基本操作篇 27/704/344/386
  • Linux系统性能调优
  • 数据库系统原理|课程回顾与习题部分参考答案
  • 区间预测 | Matlab实现QRBiTCN分位数回归双向时间卷积神经网络注意力机制时序区间预测
  • Python画图
  • Markdown:Mermaid 画图
  • 郑州专业做网站/百度投诉中心电话24个小时
  • 网页设计网站网站建设课程设计/百度查重软件
  • 家用电脑搭建网站/百度下载app下载
  • 基于jsp的社团组织网站建设/搜索引擎优化工作
  • 网站建站分为两种/新乡seo优化
  • b2b网站如何做排名/企点