整合了c++里面常用的STL及其常用API

一、容器的通用概念和 API

几乎所有 STL 容器(除少数比如 array 特例)都有一套共通的接口。

1. 常用类型别名

cpp 复制代码
using value_type      = T;                // 元素类型
using size_type       = std::size_t;      // 大小类型
using iterator        = ...;              // 迭代器类型
using const_iterator  = ...;              // 只读迭代器

一般用法:

cpp 复制代码
std::vector<int> v;
std::vector<int>::iterator it = v.begin();
std::vector<int>::size_type n = v.size();

实际写代码时很多时候用 auto 更方便。

2. 容器大小相关 API

几乎所有容器都有:

cpp 复制代码
c.size();      // 返回当前元素个数
c.empty();     // 是否为空
c.max_size();  // 最大可容纳元素个数(一般很少用)

例子:

cpp 复制代码
std::vector<int> v = {1, 2, 3};
if (!v.empty()) {
    std::cout << "size = " << v.size() << '\n';
}

3. 迭代器与遍历相关 API

通用:

cpp 复制代码
c.begin();     // 指向第一个元素
c.end();       // 指向最后一个元素"之后"的位置
c.cbegin();    // const 版本
c.cend();

遍历示例:

cpp 复制代码
std::vector<int> v = {1, 2, 3};

// 传统迭代器写法
for (auto it = v.begin(); it != v.end(); ++it) {
    std::cout << *it << ' ';
}

// range-for 写法(最常用)
for (int x : v) {
    std::cout << x << ' ';
}

4. 修改容器:clearswap

cpp 复制代码
c.clear();      // 删除所有元素
c.swap(other);  // 交换两个容器的内容,几乎是 O(1)

例子:

cpp 复制代码
std::vector<int> a = {1, 2};
std::vector<int> b = {3, 4, 5};

a.swap(b); // 现在 a = {3,4,5}, b = {1,2}

二、顺序容器:vectorstringdequelist

先重点讲最常用的 vectorstring,其他顺序容器 API 非常类似。

1. std::vector<T> 常用 API

vector 是最常用容器之一:支持随机访问,尾部增删非常快。

1.1 构造与初始化
cpp 复制代码
std::vector<int> v1;             // 空
std::vector<int> v2(10);         // 10 个 0
std::vector<int> v3(10, 42);     // 10 个 42
std::vector<int> v4 = {1, 2, 3}; // 列表初始化
1.2 访问元素
cpp 复制代码
v[i];         // 不做边界检查
v.at(i);      // 做边界检查,越界会抛异常
v.front();    // 第一个元素
v.back();     // 最后一个元素
v.data();     // 返回底层数组指针(T*)

例子:

cpp 复制代码
std::vector<int> v = {10, 20, 30};
int a = v[0];        // 10
int b = v.at(1);     // 20
int first = v.front();
int last  = v.back();
int* p    = v.data();   // 可以用于和 C API 交互
1.3 修改:push_back / pop_back / insert / erase
cpp 复制代码
v.push_back(x);             // 尾部插入
v.pop_back();               // 删除尾部一个元素
v.insert(pos, x);           // 在迭代器 pos 前插入 x
v.erase(pos);               // 删除 pos 位置的元素
v.erase(first, last);       // 删除 [first, last) 区间
v.clear();                  // 清空

例子:

cpp 复制代码
std::vector<int> v = {1, 2, 4};

v.push_back(5);  // v: 1 2 4 5

// 在第二个元素前插入 100
auto it = v.begin();
++it;            // 指向元素 2
v.insert(it, 100);  // v: 1 100 2 4 5

// 删除第一个元素
v.erase(v.begin());  // v: 100 2 4 5
1.4 预分配和容量:reserve / capacity / shrink_to_fit
cpp 复制代码
v.reserve(n);       // 预留容量,减少扩容次数
v.capacity();       // 当前容量(不等于 size)
v.shrink_to_fit();  // 建议收缩容量(实现可以不理会)

例子(写性能敏感代码时常用):

cpp 复制代码
std::vector<int> v;
v.reserve(100000);

for (int i = 0; i < 100000; ++i) {
    v.push_back(i);
}

2. std::string 常用 API(和 vector 很像,但多了字符串操作)

很多用法直接类比 vector<char>,再加上一些字符串专属 API。

2.1 常见构造
cpp 复制代码
std::string s;                // 空
std::string s1 = "hello";     // 从 C 字符串构造
std::string s2(5, 'a');       // "aaaaa"
2.2 访问
cpp 复制代码
s[i];        // 不做检查
s.at(i);     // 边界检查
s.front();   // 第一个字符
s.back();    // 最后一个字符
s.c_str();   // const char*,用于 C 接口
2.3 拼接和追加
cpp 复制代码
s += "world";
s.push_back('!');
s.append("!!!");

例子:

cpp 复制代码
std::string s = "hello";
s += " ";
s.append("world");
s.push_back('!');
std::cout << s;    // "hello world!"
2.4 截取:substr
复制代码
std::string sub = s.substr(pos);        // 从 pos 到结尾
std::string sub2 = s.substr(pos, len);  // 从 pos 开始 len 个

例:

cpp 复制代码
std::string s = "abcdef";
std::string a = s.substr(2);     // "cdef"
std::string b = s.substr(1, 3);  // "bcd"
2.5 查找:find 系列
cpp 复制代码
auto pos = s.find("abc");   // 找到返回下标,找不到返回 string::npos
auto pos2 = s.find('x');

例:

cpp 复制代码
std::string s = "hello world";
auto pos = s.find("world"); // pos = 6
if (pos != std::string::npos) {
    std::cout << "found at " << pos << '\n';
}

3. std::deque<T> 常用 API(双端队列)

特点:头尾增删都快,支持随机访问。

常用 API 和 vector 基本一样,外加:

cpp 复制代码
d.push_front(x);
d.pop_front();
d.push_back(x);
d.pop_back();

例子:

cpp 复制代码
std::deque<int> dq;
dq.push_back(2);
dq.push_front(1);   // dq: 1 2
dq.push_back(3);    // dq: 1 2 3
dq.pop_front();     // dq: 2 3

4. std::list<T> 常用 API(双向链表)

特点:任意位置插入/删除 O(1),但随机访问很慢(没有 operator[])。

基础的 push_back / push_front / insert / erase 同样有,还有:

cpp 复制代码
l.push_front(x);
l.pop_front();
l.remove(value);        // 删除所有等于 value 的元素
l.sort();               // 链表内部排序
l.reverse();            // 反转链表

例子:

cpp 复制代码
std::list<int> lst = {3, 1, 4, 1};
lst.remove(1);      // 删除所有值为 1 的节点 -> {3,4}
lst.push_front(5);  // {5,3,4}
lst.sort();         // {3,4,5}
lst.reverse();      // {5,4,3}

三、有序关联容器:set / map(红黑树)

有序关联容器底层一般是红黑树(平衡二叉搜索树),键是有序的。

1. std::set<T> 常用 API

只存 key,自动去重、自动排序。

1.1 插入与删除
cpp 复制代码
set.insert(x);
set.erase(x);          // 按值删除
set.erase(it);         // 按迭代器删除

例子:

cpp 复制代码
std::set<int> s;
s.insert(3);
s.insert(1);
s.insert(2);   // s 内部为 {1,2,3}

s.erase(2);    // 删除元素 2
1.2 查找与存在性判断
cpp 复制代码
auto it = s.find(x);      // 找不到则返回 s.end()
bool ok = s.count(x);     // 0 或 1

例子:

cpp 复制代码
if (s.count(3)) {
    std::cout << "exists\n";
}
1.3 遍历(有序)
cpp 复制代码
for (int x : s) {
    std::cout << x << ' ';  // 按从小到大输出
}

2. std::map<Key, T> 常用 API

键值对容器:key 有序、唯一。

2.1 插入与访问
cpp 复制代码
std::map<std::string, int> mp;

mp["Alice"] = 100;        // 若不存在则插入,存在则修改
mp.insert({"Bob", 90});
mp.emplace("Carol", 95);

访问:

cpp 复制代码
int v1 = mp["Alice"];     // 若不存在会插入一个默认值
int v2 = mp.at("Alice");  // 不存在则抛异常
2.2 查找和删除
cpp 复制代码
auto it = mp.find("Bob");
if (it != mp.end()) {
    std::cout << it->first << " : " << it->second << '\n';
}

mp.erase("Bob");
mp.erase(it);
2.3 遍历(按 key 有序)
cpp 复制代码
for (auto& p : mp) {
    std::cout << p.first << " => " << p.second << '\n';
}

四、哈希关联容器:unordered_set / unordered_map

底层是哈希表,平均 O(1) 插入 / 查找 / 删除,元素无序。

常用 API 和有序版非常相似,只是遍历顺序不再有序。

1. std::unordered_set<T> 常用 API

cpp 复制代码
std::unordered_set<int> st;

// 插入
st.insert(10);
st.insert(20);

// 查找
if (st.count(10)) {}

// 删除
st.erase(10);

// 遍历(无序)
for (int x : st) {
    std::cout << x << ' ';
}

2. std::unordered_map<Key, T> 常用 API

cpp 复制代码
std::unordered_map<std::string, int> mp;

// 插入 / 修改
mp["Alice"] = 100;
mp.insert({"Bob", 90});
mp.emplace("Carol", 95);

// 查找
if (mp.count("Bob")) {
    std::cout << mp["Bob"] << '\n';
}

// 使用 find 避免插入默认值
auto it = mp.find("Dave");
if (it != mp.end()) {
    std::cout << it->second;
}

// 删除
mp.erase("Bob");
mp.erase(it);

// 遍历(无序)
for (auto& p : mp) {
    std::cout << p.first << " => " << p.second << '\n';
}

五、容器适配器:stackqueuepriority_queue

这些不是"真正的底层容器",而是基于其它容器封装出的接口。

1. std::stack<T> 常用 API

默认基于 deque 实现,典型"栈"结构:后进先出。

cpp 复制代码
std::stack<int> st;

st.push(1);
st.push(2);
st.push(3);

while (!st.empty()) {
    std::cout << st.top() << ' '; // 3 2 1
    st.pop();
}

常用 API:

cpp 复制代码
st.push(x);
st.pop();
st.top();      // 栈顶元素
st.empty();
st.size();

2. std::queue<T> 常用 API

默认基于 deque 实现,典型"队列":先进先出。

cpp 复制代码
std::queue<int> q;

q.push(1);
q.push(2);
q.push(3);

while (!q.empty()) {
    std::cout << q.front() << ' '; // 1 2 3
    q.pop();
}

常用 API:

cpp 复制代码
q.push(x);     // 入队(尾部)
q.pop();       // 出队(头部)
q.front();     // 队头
q.back();      // 队尾
q.empty();
q.size();

3. std::priority_queue<T> 常用 API(优先队列)

默认是"大根堆":top() 是当前最大的元素。

cpp 复制代码
std::priority_queue<int> pq;

pq.push(3);
pq.push(10);
pq.push(5);

while (!pq.empty()) {
    std::cout << pq.top() << ' '; // 10 5 3
    pq.pop();
}

常用 API:

cpp 复制代码
pq.push(x);
pq.pop();
pq.top();
pq.empty();
pq.size();

若要"小根堆",定义方式为:

cpp 复制代码
std::priority_queue<int, std::vector<int>, std::greater<int>> minpq;

六、综合记忆小结(按类型分类)

  1. 通用(几乎所有容器)
    size, empty, clear, begin/end, swap

  2. 顺序容器(vector/string/deque/list)

    • 增删:push_back, pop_back, push_front, pop_front, insert, erase

    • 访问:operator[], at, front, back, data/c_str

    • 其他:reserve/capacity(vector)、substr/find(string)、sort/reverse/remove(list)

  3. 有序关联(set/map)

    • 插入:insert, emplace

    • 查找:find, count

    • 删除:erase

    • 遍历:范围 for,每次 set 得到元素本身,map 得到 pair<key,value>

  4. 哈希关联(unordered_set/unordered_map)

    API 基本与 set/map 一致,只是遍历无序,多了 bucket_countload_factor(一般需要时再查)。

  5. 容器适配器(stack/queue/priority_queue)

    • 核心就是 push / pop / topfront/back,配合 empty / size
相关推荐
E***q5392 小时前
后端服务限流实现,Spring Cloud Alibaba Sentinel
java·开发语言·sentinel
橘子海全栈攻城狮2 小时前
【源码+文档+调试讲解】实验室耗材管理系统springboot 094
java·开发语言·spring boot·后端·spring
Hello_Embed2 小时前
FreeRTOS 入门(四):堆的核心原理
数据结构·笔记·学习·链表·freertos·
范纹杉想快点毕业2 小时前
《嵌入式硬件从入门到精通:电源 / 模电 / 数电 / 通信核心全解析》
java·开发语言·数据库·单片机·嵌入式硬件
先生沉默先2 小时前
NodeJs 学习日志(8):雪花算法生成唯一 ID
javascript·学习·node.js
Ryan ZX2 小时前
【Go语言基础】Go语言开发环境搭建
开发语言·后端·golang
x***J3483 小时前
后端服务限流算法,计数器与滑动窗口
java·开发语言
FLPGYH3 小时前
BMC 深度解析:服务器带外管理的核心技术架构与实践
linux·服务器·c++·驱动开发
二川bro3 小时前
第51节:Three.js源码解析 - 核心架构设计
开发语言·javascript·ecmascript