[算法竞赛]九、C++标准模板库STL常用容器大全

STL主要包括容器、算法、迭代器、函数

在一般情形下挑选适合的stl进行coding可以极大的提高coding效率

但是针对一些个别的题目,需要手敲的数据结构与算法,stl的效率比不上针对特定情况下的手动的数据结构,要具体情况具体分析

vector(动态数组)

理解为可调整大小的动态数组即可

基本语法

复制代码
vector<数据类型> arr(数组长度, 内容)

初始化

操作方式 说明 示例
默认构造 创建空 vector vector<int> v;
带大小构造 创建含 n 个默认初始化元素的 vector vector<int> v(5);(5 个 0)
带大小和初始值 创建含 nval 的 vector vector<int> v(5, 10);(5 个 10)
拷贝构造 复制另一个 vector vector<int> v2(v1);vector<int> v2 = v1;

一维数组:

复制代码
    vector<int> a;  //初始化一个数组
    vector<int> b(10); //初始化一个长度为10的数组
    vector<int> c(10, 0); //初始化一个长度为10,全部为0的数组

二维数组:

可以理解为在一维数组中每个位置存放了一个一维数组

在空间上可以用平面Oxy表示

复制代码
    vector<vector<int>>a(10,vector<int>()); //初始化一个10行的二维数组 列为空
    vector<vector<int>>b(10,vector<int>(10,0)); //初始化一个10行10列 值全为0的数组

三维数组:

可以理解为在二维数组中每个位置存放了一个一维数组

在空间上可以用三维空间Oxyz表示

复制代码
    vector<vector<vector<int>>>a(10,vector<vector<int>>());//初始化一个10行0列0高数组
    vector<vector<vector<int>>>b(10,vector<vector<int>>(10,vector<int>()));//初始化一个10行10列0高的数组
    vector<vector<vector<int>>>c(10,vector<vector<int>>(10,vector<int>(10,0)));////初始化一个10行10列10高的数组

数组复制:

复制代码
vector<int>b(a)//把数组a复制到b

访问

操作 说明 注意事项
at() 带边界检查的访问(如 v.at(i) 越界时抛出 std::out_of_range 异常
front() 获取第一个元素 空容器调用未定义
back() 获取最后一个元素 空容器调用未定义
复制代码
vector<int> v = {10, 20, 30, 40};
cout << v[1] << endl;    // 20下标访问
cout << v.front() << endl;// 10首元素访问
cout << v.back() << endl; // 40尾元素访问

迭代器

迭代器类型 说明
begin() / end() 正向迭代器(begin 指向首元素,end 指向尾后位置)
rbegin() / rend() 反向迭代器(rbegin 指向尾元素,rend 指向首前位置)

rbegin和rend有一个比较容易理解的例子

当你向数组输入1>>2>>3时,数组实际上是[3,2,1]

复制代码
vector<int> v = {1, 2, 3, 4, 5};
// 正向遍历
for (auto it = v.begin(); it != v.end(); ++it) {
    cout << *it << " ";  // 输出 1 2 3 4 5
}
// 反向遍历
for (auto it = v.rbegin(); it != v.rend(); ++it) {
    cout << *it << " ";  // 输出 5 4 3 2 1
}

容量与大小

操作 说明
size() 返回当前元素个数
empty() 判断是否为空(size() == 0
capacity() 返回预分配的容量(capacity() >= size()
reserve(n) 预分配至少 n 的容量(若 n > capacity 则扩容,否则无操作)
resize(n) 调整元素个数为 n:- 若 n > size,默认初始化新元素- 若 n < size,删除末尾元素
resize(n, val) 调整大小,新元素用 val 初始化

元素的增删改

操作 说明
push_back(val) 末尾添加元素(拷贝 / 移动 val
emplace_back(args...)(C++11) 末尾直接构造 元素(args 为构造函数参数,比 push_back 高效)
pop_back() 删除末尾元素(空容器调用未定义)
insert(pos, val) 在迭代器 pos 前插入 val,返回新元素的迭代器
insert(pos, n, val) pos 前插入 nval
insert(pos, begin, end) pos 前插入迭代器范围 [begin, end) 的元素
erase(pos) 删除迭代器 pos 指向的元素,返回下一个元素的迭代器
erase(begin, end) 删除范围 [begin, end) 的元素,返回 end
clear() 清空所有元素(size 变为 0,capacity 不变)
复制代码
vector<int> v = {1, 2, 3};
v.push_back(4);              // 末尾添加 4 → [1,2,3,4]
v.emplace_back(5);           // 末尾直接构造 5 → [1,2,3,4,5]
v.pop_back();                 // 删除末尾 → [1,2,3,4]

auto it = v.insert(v.begin()+2, 10);  // 在索引 2 前插入 10 → [1,2,10,3,4]
v.erase(v.begin());          // 删除首元素 → [2,10,3,4]
v.clear();                    // 清空

stack(栈)

stack底层容器是deque,也可以用数组实现

初始化

操作 说明 代码示例
默认构造 创建空栈 stack<int> st;
拷贝构造 复制一个栈 stack<int> st2(st1);
自定义底层容器 指定用 vector/list 实现 stack<int, vector<int>> st;

基本操作

入栈

复制代码
stack<int> st;
st.push(10);  // 栈:[10]
st.push(20);  // 栈:[10, 20](20 是栈顶)

出栈

复制代码
st.pop(); // 删除 20 → 栈:[10]

返回栈顶元素

复制代码
cout << st.top(); // 输出 10
st.top() = 100;   // 修改栈顶为 100

判断栈为空

复制代码
if (st.empty()) {
    cout << "栈为空";
}

返回元素个数

复制代码
cout << st.size(); // 输出当前元素个数

queue(队列)

初始化

写法 说明
queue<int> q; 空队列
queue<int> q2(q1); 拷贝构造
queue<int, list<int>> q; 指定底层为 list

基本操作

入队

复制代码
q.push(10);
q.push(20);
q.push(30);
// 队列:10(队头)→20→30(队尾)

出队

复制代码
q.pop();   // 删除 10

队头获取

复制代码
cout << q.front();  // 20
q.front() = 200;

队尾获取

复制代码
cout << q.back();   // 30

判断空与元素个数

复制代码
if (q.empty()) 
cout << q.size();

deque(双端队列)

初始化

操作 说明 代码示例
默认构造 空 deque deque<int> dq;
大小构造 n 个默认值 deque<int> dq(5);
大小 + 初始值 n 个 val deque<int> dq(5, 10);
拷贝构造 复制另一个 deque deque<int> dq2(dq1);

访问

操作 说明
dq.front() 访问第一个元素
dq.back() 访问最后一个元素
复制代码
deque<int> dq = {10,20,30};
cout << dq[0];      // 10
cout << dq.front(); // 10
cout << dq.back();  // 30

迭代器与vector一样

操作 说明
begin() / end() 正向迭代器
rbegin() / rend() 反向迭代器

容量与大小

操作 说明
size() 元素个数
empty() 是否为空
resize(n) 调整大小,多删少补(默认 0)
resize(n, val) 新元素用 val 填充

list(链表)

初始化

操作 说明 代码示例
默认构造 空 list list<int> lt;
带大小构造 创建含 n 个默认初始化元素的 list list<int> lt(5);(5 个 0)
带大小和初始值 创建含 nval 的 list list<int> lt(5, 10);(5 个 10)
拷贝构造 复制另一个 list list<int> lt2(lt1);list<int> lt2 = lt1;

访问

链表不支持随机访问

操作 说明 注意事项
front() 获取第一个元素 空容器调用未定义
back() 获取最后一个元素 空容器调用未定义
复制代码
list<int> lt = {10, 20, 30};
cout << lt.front() << endl;  // 10(首元素)
cout << lt.back() << endl;   // 30(尾元素)

迭代器

迭代器类型 说明
begin() / end() 正向迭代器(begin 指向首元素,end 指向尾后位置)
rbegin() / rend() 反向迭代器(rbegin 指向尾元素,rend 指向首前位置)

容量与大小

操作 说明
size() 返回当前元素个数
empty() 判断是否为空(size() == 0
resize(n) 调整元素个数为 n:- 若 n > size,默认初始化新元素- 若 n < size,删除末尾元素
resize(n, val) 调整大小,新元素用 val 初始化

增删改

复制代码
list<int> lt = {1, 2, 3};
lt.push_back(4);    // 尾插 → [1,2,3,4]
lt.push_front(0);   // 头插 → [0,1,2,3,4]
lt.pop_back();      // 尾删 → [0,1,2,3]
lt.pop_front();     // 头删 → [1,2,3]

list<int> lt = {1, 2, 3};
auto it = next(lt.begin(), 1);  // 获取指向第2个元素(2)的迭代器
lt.insert(it, 10);  // 在 it 前插入 10 → [1,10,2,3]
lt.erase(it);        // 删除 it 指向的元素(2)→ [1,10,3]

list<int> lt1 = {1, 2, 3};
list<int> lt2 = {4, 5, 6};
auto it = next(lt1.begin(), 1);  // lt1 中指向 2 的迭代器
lt1.splice(it, lt2);  // 将 lt2 全部元素移动到 lt1 的 it 前
// lt1: [1,4,5,6,2,3],lt2 变为空

list<int> lt = {1, 2, 2, 3, 4, 2};
lt.remove(2);  // 删除所有 2 → [1,3,4]
lt.remove_if([](int x) { return x > 3; });  // 删除大于 3 的元素 → [1,3]

list<int> lt = {1, 2, 2, 3, 3, 3, 4};
lt.unique();  // 去重 → [1,2,3,4]

list<int> lt = {3, 1, 4, 1, 5, 9};
lt.sort();  // 升序 → [1,1,3,4,5,9]
lt.sort(greater<int>());  // 降序 → [9,5,4,3,1,1]

lt.clear();  // 清空所有元素,size 变为 0

priority_queue(优先队列/堆)

初始化

操作 说明 代码示例
默认构造 空优先队列(默认大顶堆,底层 vector) priority_queue<int> pq;
自定义比较函数 指定优先级规则(如小顶堆) priority_queue<int, vector<int>, greater<int>> pq;
自定义底层容器 deque 作为底层 priority_queue<int, deque<int>> pq;

主要操作

入队、出队、返回堆顶元素、返回队列大小、判空

复制代码
priority_queue<int> pq;
pq.push(10);
pq.push(30);
pq.push(20);
// 堆结构:30(堆顶)→20→10(默认大顶堆)
pq.pop();   // 删除堆顶 30,新堆顶为 20
cout << pq.top();  // 输出 20
pq.top() = 200;    // 修改堆顶为 200(修改后需注意堆性质可能被破坏,不建议直接修改)
if (pq.empty()) {
    cout << "队列为空";
}
cout << pq.size();

自定义优先级

自定义优先队列的排序算法

主要有两种

一种是重载运算符

复制代码
#include <iostream>
#include <queue>
#include <string>
using namespace std;

// 自定义类:学生,按成绩排序
struct Student {
    string name;
    int score;
    // 重载 < 运算符:默认大顶堆(成绩高的优先)
    bool operator<(const Student& other) const {
        return score < other.score;  // 注意:大顶堆用 <,小顶堆用 >
    }
};

int main() {
    priority_queue<Student> pq;
    pq.push({"Alice", 85});
    pq.push({"Bob", 95});
    pq.push({"Charlie", 90});
    // 堆顶:Bob(95)
    cout << pq.top().name << " " << pq.top().score << endl;  // Bob 95
    return 0;
}

一种是自定义函数对象

复制代码
#include <iostream>
#include <queue>
#include <string>
using namespace std;

struct Student {
    string name;
    int score;
};

// 自定义函数对象:小顶堆(成绩低的优先)
struct CompareScore {
    bool operator()(const Student& a, const Student& b) const {
        return a.score > b.score;  // 小顶堆用 >
    }
};

int main() {
    // 声明:底层 vector,比较函数 CompareScore
    priority_queue<Student, vector<Student>, CompareScore> pq;
    pq.push({"Alice", 85});
    pq.push({"Bob", 95});
    pq.push({"Charlie", 90});
    // 堆顶:Alice(85)
    cout << pq.top().name << " " << pq.top().score << endl;  // Alice 85
    return 0;
}

map(表)

map自带排序

注意multimap是可以多个键对应一个值

unordered_map则是不带自排序的

初始化

操作 说明 代码示例
默认构造 空 map(默认升序,键类型需支持 < 比较) map<int, string> m;
自定义比较函数 指定排序规则(如降序) map<int, string, greater<int>> m;
拷贝构造 复制另一个 map map<int, string> m2(m1);map<int, string> m2 = m1;
迭代器范围构造 从其他容器的迭代器范围初始化 map<int, string> m(m1.begin(), m1.end());

可用下标访问

迭代器同vector

容量与大小操作也同上

元素插入

操作 说明 返回值
insert(pair) 插入键值对 pair std::pair<iterator, bool>:- iterator 指向插入位置(或已存在的元素)- bool 表示是否插入成功(true 成功,false 键已存在)
insert(make_pair(key, value)) std::make_pair 构造键值对插入 同上

元素查找

操作 说明 返回值
find(key) 查找键为 key 的元素 若找到,返回指向该元素的迭代器;否则返回 end()
count(key) 统计键为 key 的元素个数 0 或 1(因为键唯一,用于判断键是否存在)
lower_bound(key) 查找第一个不小于 key 的元素 指向该元素的迭代器;若所有元素都小于 key,返回 end()
upper_bound(key) 查找第一个大于 key 的元素 指向该元素的迭代器;若所有元素都不大于 key,返回 end()
equal_range(key) 查找键为 key 的元素范围 std::pair<lower_bound(key), upper_bound(key)>(因键唯一,两个迭代器要么相同,要么指向相邻位置)
复制代码
map<int, string> m = {{1, "one"}, {3, "three"}, {5, "five"}};

// 1. find 查找
auto it = m.find(3);
if (it != m.end()) {
    cout << it->second << endl;  // "three"
}

// 2. count 判断存在
if (m.count(5)) {
    cout << "键 5 存在" << endl;
}

// 3. lower_bound 和 upper_bound
auto low = m.lower_bound(2);  // 第一个不小于 2 的是 3
auto up = m.upper_bound(4);   // 第一个大于 4 的是 5
cout << low->first << endl;  // 3
cout << up->first << endl;   // 5

// 4. equal_range
auto range = m.equal_range(3);
if (range.first != range.second) {
    cout << range.first->second << endl;  // "three"
}

set(集合)

multi和unordered用法和map差不多

注意set不能用下标访问

初始化

操作 说明 代码示例
默认构造 空 set(默认升序,元素类型需支持 < 比较) set<int> s;
自定义比较函数 指定排序规则(如降序) set<int, greater<int>> s;
拷贝构造 复制另一个 set set<int> s2(s1);set<int> s2 = s1;
迭代器范围构造 从其他容器的迭代器范围初始化(自动去重) set<int> s(v.begin(), v.end());

其他操作都跟map差不多

string(字符串)

熟悉的字符串

初始化

操作 说明 代码示例
默认构造 空字符串 string s;
带大小和字符 创建含 nc 的字符串 string s(5, 'a');("aaaaa")
拷贝构造 复制另一个 string string s2(s1);string s2 = s1;
子串构造 s1pos 位置开始,取 count 个字符(count 省略则到末尾) string s(s1, 2, 3);(从索引 2 取 3 个)
迭代器范围构造 从迭代器范围 [begin, end) 初始化 string s(s1.begin(), s1.end());

元素访问

操作 说明 注意事项
s[i] 下标访问(从 0 开始) 不检查越界,越界行为未定义
s.at(i) 带边界检查的访问 越界时抛出 std::out_of_range 异常
s.front() 访问第一个字符(s[0] 空字符串调用未定义
s.back() 访问最后一个字符(s[s.size()-1] 空字符串调用未定义
s.data() 返回指向底层字符数组的指针 C++17 前为 const char*,C++17 起为 char*(可写)
s.c_str() 返回指向底层字符数组的 const char*(以 \0 结尾) 始终为 const,用于与 C 风格接口交互
复制代码
string s = "hello";
cout << s[0] << endl;      // 'h'(下标访问)
cout << s.front() << endl;  // 'h'
cout << s.back() << endl;   // 'o'

迭代器同之前的

容量与大小也同之前的

字符串的修改

操作 说明
s.push_back(c) 末尾添加字符 c
s.pop_back() 删除末尾字符(空字符串调用未定义)

字符串可赋值操作

操作 说明
s += s2 / s += "str" / s += c 追加 string、C 字符串或字符
s.append(s2) 追加 string s2
s.append(s2, pos, count) 追加 s2pos 开始的 count 个字符
s.append("str") 追加 C 字符串
s.append("str", n) 追加 C 字符串的前 n 个字符
s.append(n, c) 追加 n 个字符 c
s.append(begin, end) 追加迭代器范围 [begin, end) 的字符

插入

操作 说明
s.insert(pos, s2) pos 位置插入 string s2
s.insert(pos, "str") pos 位置插入 C 字符串
s.insert(pos, n, c) pos 位置插入 n 个字符 c
s.insert(iterator, c) 在迭代器 iterator 前插入字符 c,返回指向新字符的迭代器
s.insert(iterator, n, c) 在迭代器前插入 n 个字符 c
s.insert(iterator, begin, end) 在迭代器前插入迭代器范围 [begin, end) 的字符

删除

操作 说明
s.erase(pos, count) pos 位置开始删除 count 个字符(count 省略则删除到末尾)
s.erase(iterator) 删除迭代器指向的字符,返回指向下一个字符的迭代器
s.erase(begin, end) 删除迭代器范围 [begin, end) 的字符,返回 end
s.clear() 清空所有字符(size 变为 0,capacity 不变)

替换

操作 说明
s.replace(pos, count, s2) pos 开始的 count 个字符替换为 s2
s.replace(pos, count, "str") 替换为 C 字符串
s.replace(pos, count, n, c) 替换为 n 个字符 c
s.replace(begin, end, s2) 替换迭代器范围 [begin, end) 的字符为 s2

查找

操作 说明
s.find(s2, pos=0) pos 开始正向 查找 string s2,返回首次出现的索引
s.find("str", pos=0) 查找 C 字符串
s.find(c, pos=0) 查找字符 c
s.rfind(s2, pos=npos) pos 开始反向查找(从后往前),返回最后一次出现的索引
s.find_first_of(s2, pos=0) pos 开始查找 s2任意字符首次出现的索引
s.find_last_of(s2, pos=npos) pos 开始反向查找 s2 中任意字符最后一次出现的索引
s.find_first_not_of(s2, pos=0) pos 开始查找不在 s2 中的字符首次出现的索引
s.find_last_not_of(s2, pos=npos) pos 开始反向查找不在 s2 中的字符最后一次出现的索引

比较

操作 说明 返回值
s.compare(s2) 比较 ss2 - <0s 字典序小于 s2- =0:相等- >0s 字典序大于 s2
s.compare(pos, count, s2) 比较 spos 开始的 count 个字符与 s2 同上
s.compare(pos, count, s2, pos2, count2) 比较 s 的子串与 s2 的子串 同上

子串操作

操作 说明
s.substr(pos=0, count=npos) 返回从 pos 开始的 count 个字符组成的子串(count 省略则到末尾)

类型修改

操作 说明 异常
stoi(s, pos=nullptr, base=10) intpos 用于存储转换后未处理的第一个字符索引,base 为进制) 转换失败抛 std::invalid_argument,溢出抛 std::out_of_range
stol(s, pos=nullptr, base=10) long 同上
stoll(s, pos=nullptr, base=10) long long 同上
stoul(s, pos=nullptr, base=10) unsigned long 同上
stoull(s, pos=nullptr, base=10) unsigned long long 同上
stof(s, pos=nullptr) float 同上
stod(s, pos=nullptr) double 同上
stold(s, pos=nullptr) long double 同上

举例

复制代码
#include <iostream>
#include <string>
using namespace std;

int main() {
    // 1. 初始化
    string s = "hello world";

    // 2. 元素访问
    cout << s[0] << " " << s.at(1) << endl;  // h e
    cout << s.front() << " " << s.back() << endl;  // h d

    // 3. 修改操作
    s += "!";                  // "hello world!"
    s.append(" 123", 3);       // "hello world! 123"
    s.insert(5, " C++");        // "hello C++ world! 123"
    s.erase(5, 4);              // "hello world! 123"
    s.replace(6, 5, "C++");     // "hello C++! 123"

    // 4. 查找操作
    size_t pos = s.find("C++");
    if (pos != string::npos) {
        cout << "找到 C++,索引:" << pos << endl;  // 6
    }

    // 5. 子串
    string sub = s.substr(6, 3);  // "C++"
    cout << "子串:" << sub << endl;

    // 6. 比较
    string s2 = "hello C++!";
    cout << (s == s2) << endl;  // 0(s 还有 " 123")

    // 7. 类型转换
    s = "456";
    int num = stoi(s);  // 456
    s = to_string(789);  // "789"

    // 8. 遍历
    for (char c : s) {
        cout << c << " ";  // 7 8 9
    }

    return 0;
}
相关推荐
永恒_顺其自然2 小时前
Java Web 传统项目异步分块上传系统实现方案
java·开发语言·前端
bu_shuo2 小时前
c++中对数组求和
开发语言·c++
赫瑞2 小时前
Java中的大数处理 —— BigInteger
java·开发语言
r_oo_ki_e_2 小时前
java25--Collection集合
java·开发语言
elseif1232 小时前
【Markdown】指南(上)
linux·开发语言·前端·javascript·c++·笔记
星辰徐哥3 小时前
C++网络编程:TCP服务器与客户端的实现
网络·c++·tcp/ip
初九之潜龙勿用3 小时前
C# 解决“因为算法不同,客户端和服务器无法通信”的问题
服务器·开发语言·网络协议·网络安全·c#
不知名。。。。。。。。3 小时前
Qt常用控件
开发语言·qt
顾温3 小时前
数据转换函数
开发语言·算法