常用 C++ STL 用法


前言

C++ 标准模板库 (STL, Standard Template Library):包含一些常用数据结构与算法的模板的 C++ 软件库,其包含六个组件——算法 (Algorithms)、容器 (Containers)、仿函数 (Functors)、迭代器 (Iterators),适配器以及空间适配器。

  • 1、容器:存放数据
  • 2、算法:操作数据
  • 3、迭代器:算法通过迭代器操作容器数据
  • 4、仿函数:为算法提供更多的策略
  • 5、适配器:为算法提供更多参数的接口
  • 6、空间配置器:为算法和容器动态分配、管理空间

在这里插入图片描述

示例:

  • 算法:sort(a.begin(), a.end())
  • 容器:priority_queue<int> pq
  • 仿函数:greater<int>()
  • 迭代器:vector<int>::iterator it = a.begin()

一、容器

容器库是一些通用的类模板与算法的汇集,允许程序员简单地实现如队列、链表和栈这样的常见数据结构。
在这里插入图片描述
主要常用的容器如下所示:

  • 顺序容器: arrayvectordequelist
  • 关联容器: setmapmultisetmultimap
  • 无序关联容器、unordered_setunordered_mapunordered_multisetunordered_multimap
  • 容器适配器:stackqueuepriority_queue
  • 字符串:string (basic_string<char>)
  • 对与元组: pairtuple

1. 向量 vector

std::vector 是 C++ 标准库中的一个模板类,用于表示动态数组。与普通数组不同,vector 能够自动调整大小,并提供了一些方便的成员函数来进行元素的管理。std::vector 位于头文件#include <vector>中。

1.1常用成员函数

在这里插入图片描述

1.1.1构造函数

vector<类型> arr(长度, [初值])

时间复杂度: O ( n ) O(n) O(n)

常用的一维和二维数组构造示例,高维也是一样的(就是会有点长).

vector<int> arr;         // 构造int数组
vector<int> arr(100);    // 构造初始长100的int数组
vector<int> arr(100, 1); // 构造初始长100的int数组,初值为1

vector<vector<int>> mat(100, vector<int> ());       // 构造初始100行,不指定列数的二维数组
vector<vector<int>> mat(100, vector<int> (666, -1)) // 构造初始100行,初始666列的二维数组,初值为-1

构造二维数组的奇葩写法,千万别用:

vector<int> arr[100];         // 正确,构造初始100行,不指定列数的二维数组,可用于链式前向星存图
vector<int> arr[100](100, 1); // 语法错误!
vector<int> arr(100, 1)[100]; // 语法错误!
vector<int> arr[100] {
   {
   100, 1}, 这里省略98,{
   100, 1}}; // 正确但奇葩,使用列表初始化
1.1.2 访问元素
  • 中括号运算符operator[]:使用索引访问元素,和一般数组一样的作用。时间复杂度: O ( 1 ) O(1) O(1)
  • at(size_type n):安全的访问指定位置的元素
  • front():返回第一个元素的引用
  • back():返回最后一个元素的引用
1.1.3 大小和容量
  • size()获取当前 vector 的长度,时间复杂度: O ( 1 ) O(1) O(1)
for (int i = 0; i < arr.size(); i++)
    cout << a[i] << endl;
  • capacity():返回在重新分配内存之前 vector 可以容纳的元素数量。
  • resize(新长度, [默认值]):调整 vector 的大小,时间复杂度: O ( n ) O(n) O(n)
    • 如果是缩短,则删除多余的值
    • 如果是扩大,且指定了默认值,则新元素均为默认值**(旧元素不变)**
  • reserve(size_type n):调整 vector 的容量。
  • empty():判断 vector 是否为空。如果是空返回 true 反之返回 false.时间复杂度: O ( 1 ) O(1) O(1)
1.1.4 修改元素
  • .push_back(元素):在 vector 尾接一个元素,数组长度 + 1 +1 +1.
  • .pop_back():删除 vector 尾部的一个元素,数组长度 − 1 -1 1

时间复杂度:均摊 O ( 1 ) O(1) O(1)

// init: arr = []
arr.push_back(1);
// after: arr = [1]
arr.push_back(2);
// after: arr = [1, 2]
arr.pop_back();
// after: arr = [1]
arr.pop_back();
// after: arr = []
  • insert(iterator pos, const T& value):在指定位置插入元素。这里的位置类型是iterator 。
  • erase(iterator pos):删除指定位置的元素。
  • clear():清空 vector 中的所有元素。时间复杂度: O ( n ) O(n) O(n)
// 使用 insert 和 erase 修改元素
arr.insert(arr.begin() + 2, 10); // 在索引 2 位置插入 10
arr.erase(arr.begin() + 4);      // 删除索引 4 位置的元素
1.1.5 迭代器
  • begin():返回指向第一个元素的迭代器
  • end():返回指向最后一个元素之后的迭代器
  • rbegin():返回指向最后一个元素的反向迭代器。
  • rend():返回指向第一个元素之前的反向迭代器。
// 使用迭代器遍历 vector
for (auto it = arr.begin(); arr!= v3.end(); ++it)
{
   
    std::cout << *it << " ";
}

1.2 适用情形

一般情况 vector 可以替换掉普通数组,除非该题卡常。

有些情况普通数组没法解决: n × m n\times m n×m 的矩阵, 1 ≤ n , m ≤ 1 0 6 1\leq n,m\leq 10^6 1n,m106 n × m ≤ 1 0 6 n\times m \leq 10^6 n×m106

  • 如果用普通数组 int mat[1000010][1000010],浪费内存,会导致 MLE。
  • 如果使用 vector<vector<int>> mat(n + 10, vector<int> (m + 10)),完美解决该问题。

另外,vector 的数据储存在堆空间中,不会爆栈。

2.双端队列deque

std::deque 是 C++ 标准库中的一种双端队列容器,它允许在序列的两端进行高效的插入和删除操作。deque 的全称是 "double-ended queue"(双端队列)。它可以看作是一个动态数组的扩展,可以在头部和尾部进行操作
在这里插入图片描述

2.1 常用成员方法

作用 用法 示例
构造 deque<类型> d deque<int> d;
在前端插入元素 .push_front(元素) d.push_front(1);
在后端插入元素 .push_back(元素) d.push_back(1);
移除前端元素 .pop_front() d.pop_front();
移除后端元素 .pop_back() d.pop_back();
访问前/后端元素 .front()/.back() int a = d.front()/back();
访问元素 .at()/.operator[] int a = d.at(1);/d[1]
查看大小 / 清空 / 判空 .size()/.clear()/.empty()

2.2 适用情形

std::deque 的内存布局可能会比 std::vector 更复杂,因为它通常使用多个内存块来实现双端操作。这使得在两端操作时比 std::vector 更高效,但在内部存储和访问方面可能不如 std::vector 连续。

std::deque 在前端和后端的插入和删除操作是高效的(常数时间复杂度),而在中间进行插入或删除操作的性能类似于 std::vector,其需要在容器的两端频繁进行插入和删除操作的场景中使用。

3.栈 stack

在C++中,栈(stack)是一个后进先出(LIFO, Last In First Out)数据结构。C++标准库提供了一个 stack 类模板,位于 #include <stack> 头文件中,用于实现栈操作。栈的主要特点是只能在栈顶进行插入和删除操作,这保证了数据的顺序性。 通过二次封装双端队列 (deque) 容器,实现先进后出的栈数据结构。

3.1 常用成员方法

作用 用法 示例
构造 stack<类型> stk stack<int> stk;
将元素压入栈顶 .push(元素) stk.push(1);
移除栈顶元素 .pop() stk.pop();
访问栈顶元素,但不移除它 .top() int a = stk.top();
查看大小 / 清空 / 判空 .size()/.pop()/.empty()

3.2 适用情形

vector 也可以当栈用,vector 的 .back() 取尾部元素,就相当于取栈顶,.push_back() 相当于进栈,.pop_back() 相当于出栈。

注意事项: 不可访问内部元素下面都是错误用法

for (int i = 0; i < stk.size(); i++)
    cout << stk[i] << endl;
for (auto ele : stk)
    cout << stk << endl;

4 队列queue

队列(queue)是一种先进先出(FIFO, First In First Out)数据结构。它的基本操作包括入队(enqueue)和出队(dequeue),其中元素的入队发生在队列的尾部,出队发生在队列的头部。C++标准库提供了一个 queue 类模板,位于 #include <queue> 头文件中,用于实现队列操作。通过二次封装双端队列 (deque) 容器,实现先进先出的队列数据结构。

4.1常用方法

作用 用法 示例
构造 queue<类型> que queue<int> que;
进队,加入队尾 .push(元素) que.push(1);
出队,移除队首元素 .pop() que.pop();
取队首 .front() int a = que.front();
取队尾 .back() int a = que.back();
查看大小 / 清空 / 判空 .size()/.pop()/.empty()

4.2适用情形

在图的广度优先搜索(BFS)算法中,队列用于记录待访问的节点,确保按照层次顺序访问图中的节点。在多线程或进程间通信中,队列用于实现消息的传递和处理

注意事项: 不可访问内部元素!下面都是错误用法

for (int i = 0; i < que.size(); i++)
    cout << que[i] << endl;
for (auto ele : que)
    cout << ele << endl;

5.优先队列 priority_queue

std::priority_queue 是 C++ 标准库中提供的一个容器适配器,头文件 #include <queue>,它基于堆实现,主要用于高效地管理具有优先级的元素。它通常用于优先级队列能够保证每次访问或删除操作都是对当前最大或最小元素的操作(取决于堆的类型)。提供常数时间的最大元素查找,对数时间的插入与提取,底层原理是 二叉堆

主要特点

  • 优先级:std::priority_queue 确保每次从队列中取出的元素都是当前队列中优先级最高的元素
  • 底层实现:std::priority_queue 通常使用最大堆(最大二叉堆)实现,底层是一个二叉堆,确保每个父节点的值都大于或等于其子节点的值
  • 操作:支持常见的优先队列操作,包括插入元素、访问和删除优先级最高的元素。

5.1 常用方法

5.1.1构造函数
template <class T, class Container = std::vector<T>, class Compare = std::less<typename Container::value_type>>
class priority_queue;
  • T: 队列中元素的类型
  • Container: 用于存储元素的底层容器类型,默认为 std::vector<T>
  • Compare: 元素的比较函数对象,决定优先级的排序,默认为 std::less<T>,即最大堆。

简化后:

priority_queue<类型, 容器, 比较器> pque

  • 类型:要储存的数据类型
  • 容器:储存数据的底层容器,默认为 vector<类型>,竞赛中保持默认即可
  • 比较器:比较大小使用的比较器,默认为 less<类型>,可自定义
// 储存int的大顶堆
priority_queue<int> pq1;                            

// 储存int的小顶堆
priority_queue<int, vector<int>, greater<int>> pq2; 

// 使用自定义比较函数(最小堆)
auto compare = [](int a, int b) {
    return a > b; };
priority_queue<int, vector<int>, decltype(compare)> minHeap(compare);

std::greater<int> 是 C++ 标准库中的一个比较函数对象,用于定义大于比较操作。它是一个模板类的实例,用于将比较函数封装为函数对象。使用 std::greater<int> 可以轻松地实现优先队列的最小堆(即小顶堆)等场景。

5.1.2其他
作用 用法 示例
进堆 .push(元素) que.push(1);
出堆(优先级最高) .pop() que.pop();
取堆顶(优先级最高) .top() int a = que.top();
查看大小 / 判空 .size()/ .empty()

进出队复杂度 O ( log ⁡ n ) O(\log n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Super.Bear

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值