C++ STL 容器 总结(经DeepSeek整理)

容器数据接口及时间复杂度总结

以下是 C++ STL 容器的底层数据结构及增删查时间复杂度总结:

容器 底层数据结构 插入(平均) 删除(平均) 查找(平均) 备注
vector 动态数组 O(n) O(n) O(1)(索引) 尾部插入/删除 O(1)
deque 分块数组 + 双端队列 O(1)(头尾) O(1)(头尾) O(1)(索引) 中间插入/删除 O(n)
list 双向链表 O(1) O(1) O(n) 需已知位置迭代器
forward_list 单向链表 O(1) O(1) O(n) 需已知前驱迭代器
array 静态数组 不支持 不支持 O(1)(索引) 固定大小
stack 默认基于 deque O(1) O(1) 适配器,LIFO
queue 默认基于 deque O(1) O(1) 适配器,FIFO
priority_queue 默认基于 vector + 堆 O(log n) O(log n) O(1)(顶部) 适配器,堆结构
set 红黑树 O(log n) O(log n) O(log n) 元素唯一,有序
multiset 红黑树 O(log n) O(log n) O(log n) 元素可重复,有序
map 红黑树 O(log n) O(log n) O(log n) 键唯一,有序
multimap 红黑树 O(log n) O(log n) O(log n) 键可重复,有序
unordered_set 哈希表 O(1) O(1) O(1) 元素唯一,无序
unordered_multiset 哈希表 O(1) O(1) O(1) 元素可重复,无序
unordered_map 哈希表 O(1) O(1) O(1) 键唯一,无序
unordered_multimap 哈希表 O(1) O(1) O(1) 键可重复,无序

关键说明:

  1. 哈希容器 的时间复杂度为平均情况,最坏情况(全冲突)为 O(n)
  2. 树形容器(set/map)始终保持有序状态
  3. 序列容器 的插入/删除复杂度取决于操作位置
  4. 适配器容器(stack/queue/priority_queue)仅支持特定操作

此表格提供了常见操作的时间复杂度概览,实际性能可能受具体实现和数据分布影响。

C++ STL 容器常用操作示例及公共方法总结

各容器增删改查遍历常用示例

1. vector

#include <vector>
#include <algorithm>
#include <iostream>

void vector_example() {
    std::vector<int> vec = {1, 2, 3};
    
    // 增
    vec.push_back(4);                    // 尾部插入
    vec.insert(vec.begin() + 1, 5);      // 指定位置插入
    vec.emplace_back(6);                 // 原位构造
    
    // 删
    vec.pop_back();                      // 尾部删除
    vec.erase(vec.begin() + 1);          // 删除指定位置
    vec.erase(std::remove(vec.begin(), vec.end(), 3), vec.end()); // 删除特定值
    
    // 改
    vec[0] = 10;                         // 通过索引修改
    vec.at(1) = 20;                      // 带边界检查的修改
    std::replace(vec.begin(), vec.end(), 2, 200); // 替换特定值
    
    // 查
    int val = vec[2];                    // 通过索引访问
    auto it = std::find(vec.begin(), vec.end(), 5); // 查找元素
    bool has_value = std::binary_search(vec.begin(), vec.end(), 10); // 二分查找
    
    // 遍历
    std::cout << "vector遍历: ";
    for (size_t i = 0; i < vec.size(); ++i) {
        std::cout << vec[i] << " ";
    }
    std::cout << std::endl;
    
    // 迭代器遍历
    for (auto it = vec.begin(); it != vec.end(); ++it) {
        std::cout << *it << " ";
    }
    
    // 范围for循环
    for (const auto& element : vec) {
        std::cout << element << " ";
    }
}

2. list

#include <list>
#include <iostream>

void list_example() {
    std::list<int> lst = {1, 2, 3};
    
    // 增
    lst.push_back(4);                    // 尾部插入
    lst.push_front(0);                   // 头部插入
    lst.insert(std::next(lst.begin()), 5); // 指定位置插入
    
    // 删
    lst.pop_back();                      // 尾部删除
    lst.pop_front();                     // 头部删除
    lst.erase(std::next(lst.begin()));   // 删除指定位置
    lst.remove(2);                       // 删除所有值为2的元素
    
    // 改
    *lst.begin() = 10;                   // 通过迭代器修改
    std::replace(lst.begin(), lst.end(), 3, 30);
    
    // 查
    auto it = std::find(lst.begin(), lst.end(), 5);
    bool found = (it != lst.end());
    
    // 遍历
    std::cout << "list遍历: ";
    for (const auto& element : lst) {
        std::cout << element << " ";
    }
    std::cout << std::endl;
}

3. deque

#include <deque>
#include <iostream>

void deque_example() {
    std::deque<int> dq = {1, 2, 3};
    
    // 增
    dq.push_back(4);                     // 尾部插入
    dq.push_front(0);                    // 头部插入
    dq.insert(dq.begin() + 2, 5);        // 指定位置插入
    
    // 删
    dq.pop_back();                       // 尾部删除
    dq.pop_front();                      // 头部删除
    dq.erase(dq.begin() + 1);            // 删除指定位置
    
    // 改
    dq[0] = 10;
    dq.at(1) = 20;
    
    // 查
    int front = dq.front();
    int back = dq.back();
    
    // 遍历
    std::cout << "deque遍历: ";
    for (const auto& element : dq) {
        std::cout << element << " ";
    }
    std::cout << std::endl;
}

4. map

#include <map>
#include <iostream>

void map_example() {
    std::map<int, std::string> m = {{1, "one"}, {2, "two"}, {3, "three"}};
    
    // 增
    m[4] = "four";                       // 使用下标插入
    m.insert({5, "five"});               // 使用insert插入
    m.emplace(6, "six");                 // 原位构造
    
    // 删
    m.erase(2);                          // 按键删除
    m.erase(m.find(3));                  // 按迭代器删除
    
    // 改
    m[1] = "ONE";                        // 修改值
    m.at(4) = "FOUR";                    // 带检查的修改
    
    // 查
    auto it = m.find(1);                 // 查找键
    if (it != m.end()) {
        std::cout << "找到: " << it->second << std::endl;
    }
    bool exists = m.count(5) > 0;        // 检查键是否存在
    
    // 遍历
    std::cout << "map遍历: ";
    for (const auto& pair : m) {
        std::cout << "{" << pair.first << ": " << pair.second << "} ";
    }
    std::cout << std::endl;
}

5. set

#include <set>
#include <iostream>

void set_example() {
    std::set<int> s = {1, 2, 3, 4, 5};
    
    // 增
    s.insert(6);
    s.emplace(7);
    
    // 删
    s.erase(2);
    s.erase(s.find(3));
    
    // 改: set元素不可直接修改,需要先删除再插入
    
    // 查
    auto it = s.find(4);
    bool exists = s.count(5) > 0;
    auto lb = s.lower_bound(3);          // 第一个不小于3的元素
    auto ub = s.upper_bound(3);          // 第一个大于3的元素
    
    // 遍历
    std::cout << "set遍历: ";
    for (const auto& element : s) {
        std::cout << element << " ";
    }
    std::cout << std::endl;
}

6. unordered_map

#include <unordered_map>
#include <iostream>

void unordered_map_example() {
    std::unordered_map<int, std::string> um = {{1, "one"}, {2, "two"}};
    
    // 增
    um[3] = "three";
    um.insert({4, "four"});
    
    // 删
    um.erase(2);
    
    // 改
    um[1] = "ONE";
    
    // 查
    auto it = um.find(1);
    bool exists = um.count(3) > 0;
    
    // 遍历
    std::cout << "unordered_map遍历: ";
    for (const auto& pair : um) {
        std::cout << "{" << pair.first << ": " << pair.second << "} ";
    }
    std::cout << std::endl;
}

容器公共方法总结

所有容器共有的方法

方法 描述 示例
size() 返回元素数量 vec.size()
empty() 检查是否为空 if (cont.empty())
clear() 清空所有元素 cont.clear()
begin()/end() 返回迭代器 auto it = cont.begin()
cbegin()/cend() 返回const迭代器 auto cit = cont.cbegin()
swap(other) 交换两个容器 cont1.swap(cont2)

序列容器特有方法 (vector, list, deque, array)

方法 描述 适用容器
front() 访问第一个元素 除forward_list外
back() 访问最后一个元素 除forward_list外
push_back() 尾部插入 vector, list, deque
pop_back() 尾部删除 vector, list, deque
push_front() 头部插入 list, deque
pop_front() 头部删除 list, deque
insert(pos, value) 指定位置插入 所有序列容器
erase(pos) 删除指定位置 所有序列容器

关联容器特有方法 (set, map, multiset, multimap)

方法 描述 示例
find(key) 查找元素 s.find(key)
count(key) 统计出现次数 m.count(key)
lower_bound(key) 返回第一个不小于key的迭代器 s.lower_bound(key)
upper_bound(key) 返回第一个大于key的迭代器 s.upper_bound(key)
equal_range(key) 返回匹配key的范围 auto range = m.equal_range(key)

无序容器特有方法 (unordered_*)

方法 描述 示例
bucket_count() 返回桶的数量 um.bucket_count()
load_factor() 返回负载因子 um.load_factor()
rehash(n) 设置桶的数量 um.rehash(100)
reserve(n) 预留空间 um.reserve(1000)

迭代器相关方法

方法 描述 示例
begin()/end() 正向迭代器 for (auto it = cont.begin(); ...)
rbegin()/rend() 反向迭代器 for (auto rit = cont.rbegin(); ...)
cbegin()/cend() const正向迭代器 只读遍历
crbegin()/crend() const反向迭代器 只读反向遍历

容量相关方法

方法 描述 适用容器
size() 当前元素数量 除forward_list外
max_size() 最大可能大小 所有
resize(n) 调整大小 序列容器
capacity() 当前容量 vector, string
reserve(n) 预留容量 vector, string, unordered_*
shrink_to_fit() 减少容量到适合 vector, deque, string

使用建议总结

选择容器的指导原则:

  1. 需要随机访问vector, deque, array
  2. 频繁在中间插入删除list, forward_list
  3. 需要有序存储和快速查找set, map
  4. 只需要快速查找,不关心顺序unordered_set, unordered_map
  5. 需要双端操作deque
  6. 固定大小array

性能提示:

  • vector 在尾部操作高效,中间操作昂贵
  • list 在任何位置插入删除都高效,但访问慢
  • 关联容器保持元素有序,查找为 O(log n)
  • 无序容器查找为平均 O(1),最坏 O(n)

这些示例和方法覆盖了 STL 容器的主要使用场景,掌握这些操作能够满足日常开发的大部分需求。

posted @ 2025-10-15 22:22  焦涛  阅读(16)  评论(0)    收藏  举报