C++常见STL容器及其用法

系列文章目录


本文用于记录本人学习过程中遇到的C++常见STL容器及其用法,以及常用函数,会不断更新…


前言

C++万能头文件

#include<bits/stdc++.h>

几乎包含所有的可用到的C++库函数
但是再比赛中,使用 #include<bits/stdc++.h> 是不被推荐的,因为这个头文件包含了非常多的标准 C++ 头文件,可能会导致编译时间增加,而且可能会引发一些不必要的问题。算法 比赛通常是在有限的时间内解决问题,效率和准确性都非常重要。使用过于庞大的头文件可能会导致代码运行速度变慢,影响代码的执行效率。另外,一些评测系统可能会对使用该头文件进行限制,甚至可能不支持这个头文件。

在 C++ 算法比赛中,常用的头文件有:

#include <iostream>  // 输入输出流,包括 cin 和 cout
#include <vector>    // 向量(动态数组)操作
#include <algorithm> // 算法操作,如排序、查找、最大最小值等
#include <string>    // 字符串操作,如连接字符串、查找子串等
#include <queue>     // 队列操作,常见的有 queue 和 priority_queue
#include <stack>     // 栈操作,常见的有 stack
#include <set>       // 集合操作,常见的有 set
#include <map>       // 映射操作,常见的有 map
#include <unordered_set> // 无序集合操作
#include <unordered_map> // 无序映射操作
#include <cmath>     // 数学运算,包括常用的数学函数和常量
#include <cstring>   // C 风格字符串操作,如字符串复制、字符串比较等
#include <cctype>    // 字符类型判断,如判断是否是字母、是否是数字等

在算法比赛中,头文件的选择要根据题目的需求来决定,避免不必要的冗余和影响代码的运行效率。
同时,熟悉这些头文件的用法和常见的算法操作是提高比赛编程效率和解题能力的关键。


下列均默认已经使用

using namespace std;

一、vector(向量、动态数组)

1. 头文件

#include<vector>

2.声明

vector<int> vec; // 声明一个空的 int 类型的 vector
vector<int> vec = {1, 2, 3, 4, 5}; // 声明并初始化一个包含 1, 2, 3, 4, 5 的 int 类型的 vector
vector<int> vec(5, 10); // 声明一个大小为 5 的 int 类型的 vector,所有元素都初始化为 10

int 可以替换为其他类型,任意合法的 C++ 数据类型,包括结构体

3.常用函数

下面是常用的 vector 函数及其作用和参数的简要介绍:

函数作用参数
push_back(val)在尾部添加元素val:要添加的元素
pop_back()删除尾部元素
size()获取元素个数
clear()清空 vector 中的所有元素
empty()判断 vector 是否为空
front()获取首个元素
back()获取最后一个元素
begin()返回指向首元素的迭代器
end()返回指向尾元素后一位置的迭代器
rbegin()返回指向逆向首元素的迭代器
rend()返回指向逆向尾元素后一位置的迭代器
insert(pos, val)在指定位置插入元素pos:插入位置的迭代器,val:要插入的元素
erase(pos)删除指定位置的元素pos:要删除元素的位置的迭代器
erase(start, end)删除指定范围内的元素start:要删除范围的起始位置的迭代器,end:要删除范围的末尾位置的迭代器
resize(size)重新调整 vector 的大小size:新的大小
resize(size, val)重新调整 vector 的大小并赋值size:新的大小,val:填充的元素值
swap(other)交换两个 vector 的元素other:要交换的另一个 vector

这些函数是 vector 中常用的操作函数,通过它们可以实现 vector 的常见操作,如添加、删除、访问元素等。在算法竞赛中,这些函数非常有用,可以帮助处理动态数组的问题。

二、queue(循环队列)

1. 头文件

#include<queue>

2.声明

queue<T> q;             			//声明一个存储类型为T的队列                  
queue<T, Container> q; 	 		//声明一个使用容器`Container`来实现的队列    

3.常用函数

函数描述参数
push(element)将元素element添加到队列的末尾element: 要添加的元素
pop()移除队列头部的元素,即最先进入队列的元素
front()返回队列头部的元素,但不移除该元素
back()返回队列尾部的元素,但不移除该元素
empty()判断队列是否为空,如果队列为空返回true,否则返回false
size()返回队列中元素的个数

注意:queue容器适配器不支持迭代器,因此不能使用迭代器访问队列中的元素。


三、priority_queue(优先队列/大根二叉堆)

1. 头文件

#include<queue>

2.声明

priority_queue<T> pq;              //声明一个存储类型为T的默认大顶堆 
priority_queue<T, Container> pq;   //声明一个使用容器`Container`来实现的默认大顶堆

注意:priority_queue容器适配器是一个大顶堆,默认情况下按照元素的大小进行降序排序。可以通过重载比较函数来改变排序方式,实现小顶堆。在声明时,可以使用自定义的比较函数或容器来创建优先队列。

// 创建小顶堆,按元素的大小进行升序排序
priority_queue<int, vector<int>, greater<int>> pq;

// 自定义比较函数,创建小顶堆
struct Compare {
    bool operator()(int a, int b) {
        return a > b; // 升序排序
    }
};
priority_queue<int, vector<int>, Compare> pq;

3.常用函数

函数描述参数
push(element)将元素element添加到优先队列中,插入后会自动调整成大顶堆element: 要添加的元素
pop()移除优先队列中的顶部元素,即最大元素
top()返回优先队列中的顶部元素,即最大元素
empty()判断优先队列是否为空,如果队列为空返回true,否则返回false
size()返回优先队列中元素的个数

四、deque(双端队列)

1. 头文件

#include<deque>

2.声明

deque<T> dq;			// 声明一个存储类型为T的双端队列

3.常用函数

函数描述参数
push_back(val)在双端队列的末尾插入元素valval: 要插入的元素
push_front(val)在双端队列的头部插入元素valval: 要插入的元素
pop_back()移除双端队列末尾的元素
pop_front()移除双端队列头部的元素
back()返回双端队列末尾的元素
front()返回双端队列头部的元素
empty()判断双端队列是否为空,如果队列为空返回true,否则返回false
size()返回双端队列中元素的个数
clear()移除双端队列中的所有元素

deque是一个双端队列,可以在队列的头部和尾部高效地插入和删除元素,因此在某些场景下比vector更加合适。另外,deque的迭代器也支持随机访问,可以使用下标或迭代器来访问其中的元素。


五、set/multiset(有序集合/无序多重级)

set是一个集合,其中的元素按照从小到大的顺序排列,且不允许有重复的元素。multiset是一个多重集合,其中的元素按照从小到大的顺序排列,允许有重复的元素。

setmultiset容器内部实现了红黑树,因此查找、插入和删除操作的时间复杂度为O(log n),其中n为集合中元素的个数。由于集合中的元素是有序的,所以可以进行范围查找和范围删除操作。另外,setmultiset的迭代器是双向迭代器,支持反向遍历。

1. 头文件

#include<set>

2.声明

set<T> s;			//声明一个存储类型为T的集合  
multiset<T> ms;      //声明一个存储类型为T的多重集合  

3.常用函数

两者支撑的函数基本相同

函数描述参数
insert(val)在集合中插入元素valval: 要插入的元素
erase(val)从集合中移除元素valval: 要移除的元素
find(val)查找集合中的元素val,如果找到则返回元素的迭代器,否则返回集合尾部迭代器val: 要查找的元素
count(val)统计集合中等于val的元素的个数val: 要统计的元素
lower_bound(val)返回一个指向第一个大于等于val的元素的迭代器val: 要查找的元素
upper_bound(val)返回一个指向第一个大于val的元素的迭代器val: 要查找的元素
empty()判断集合是否为空,如果集合为空返回true,否则返回false
size()返回集合中元素的个数
clear()移除集合中的所有元素

六、unordered_set(无序集合)

unordered_set是一个无序集合,其中的元素没有特定的顺序,且不允许有重复的元素。unordered_set容器内部使用哈希表来实现,因此查找、插入和删除操作的平均时间复杂度为O(1),最坏情况下的时间复杂度为O(n),其中n为集合中元素的个数。由于无序集合中的元素没有特定的顺序,因此不支持范围查找和范围删除操作。另外,unordered_set的迭代器是正向迭代器,不支持反向遍历。

1. 头文件

#include<unordered_set>

2.声明

unordered_set<T> s;		//声明一个存储类型为T的无序集合

3.常用函数

函数描述参数
insert(val)在无序集合中插入元素valval: 要插入的元素
erase(val)从无序集合中移除元素valval: 要移除的元素
find(val)查找无序集合中的元素val,如果找到则返回元素的迭代器,否则返回集合尾部迭代器val: 要查找的元素
count(val)统计无序集合中等于val的元素的个数val: 要统计的元素
empty()判断无序集合是否为空,如果集合为空返回true,否则返回false
size()返回无序集合中元素的个数
clear()移除无序集合中的所有元素

七、map(有序映射容器)

map是一个有序映射容器,其中的元素按照键的大小进行排序。map容器内部使用红黑树来实现,因此插入、删除和查找操作的平均时间复杂度为O(log n),其中n为map中元素的个数。map容器不允许有重复的键,如果插入一个已经存在的键,则新的值会覆盖原来的值。map的迭代器是正向迭代器,可以用于遍历map中的键值对,并且按照键的大小从小到大的顺序进行遍历。这种形式的map容器在算法比赛中常常用于建立映射关系和按键查找值的需求。

1. 头文件

#include<map>

2.声明

map<Key, T> m;   //声明一个存储键值对的有序映射容器,其中Key为键的类型,T为值的类型

3.常用函数

函数描述参数
insert(make_pair(key, val))在map中插入键值对(key, val)key: 要插入的键, val: 要插入的值
erase(key)从map中移除键为key的键值对key: 要移除的键
find(key)查找map中键为key的键值对,如果找到则返回键值对的迭代器,否则返回map的尾部迭代器key: 要查找的键
count(key)统计map中键为key的键值对的个数key: 要统计的键
empty()判断map是否为空,如果map为空返回true,否则返回false
size()返回map中键值对的个数
clear()移除map中的所有键值对

八、unordered_map(无序映射容器)

unordered_map是一个无序映射容器,其中的键值对没有特定的顺序,且不允许有重复的键。unordered_map容器内部使用哈希表来实现,因此插入、删除和查找操作的平均时间复杂度为O(1),最坏情况下的时间复杂度为O(n),其中n为无序映射中键值对的个数。由于无序映射中的键值对没有特定的顺序,因此不支持范围查找和范围删除操作。另外,unordered_map的迭代器是正向迭代器,不支持反向遍历。这种形式的unordered_map容器在算法比赛中常常用于建立映射关系和按键查找值的需求。

1. 头文件

#include<unordered_map>

2.声明

unordered_map<Key, T> umap;//声明一个存储键值对的无序映射容器,其中Key为键的类型,T为值的类型  

3.常用函数

函数描述参数
insert(make_pair(key, val))在无序映射中插入键值对(key, val)key: 要插入的键, val: 要插入的值
erase(key)从无序映射中移除键为key的键值对key: 要移除的键
find(key)查找无序映射中键为key的键值对,如果找到则返回键值对的迭代器,否则返回无序映射的尾部迭代器key: 要查找的键
count(key)统计无序映射中键为key的键值对的个数key: 要统计的键
empty()判断无序映射是否为空,如果无序映射为空返回true,否则返回false
size()返回无序映射中键值对的个数
clear()移除无序映射中的所有键值对

九、bitset(存储二进制)

bitset是一个固定大小的位集合容器,可以存储一系列的位值,每一位可以是0或1。bitset容器支持按位操作,例如设置位、清除位、取反位等。位集合中的位数是在编译时确定的,因此需要在声明时指定位数N。bitset容器的底层实现通常使用一个或多个unsigned long类型的整数来存储位值,因此其存储空间非常高效。

bitset在算法比赛中常常用于处理位运算问题,例如处理二进制表示的状态信息、位掩码等。它在处理一些特定问题时非常高效,并且能够有效地节省存储空间。

关于位运算的知识可以看这篇博客
链接: 位运算

1. 头文件

#include<bitset>

2.声明

bitset<N> bs;		// 声明一个大小为N的位集合,其中N为位数

3.常用函数

下面是bitset容器的声明和常用函数:

函数描述参数
set()将所有位设置为1
reset()将所有位设置为0
flip(pos)将指定位置pos的位取反pos: 要取反的位位置
test(pos)测试指定位置pos的位是否为1pos: 要测试的位位置
count()统计位集合中1的个数
size()返回位集合中的位数
to_string()将位集合转换为字符串表示
to_ulong()将位集合转换为unsigned long类型的整数
to_ullong()将位集合转换为unsigned long long类型的整数

十、stack(栈)

<stack> 是 C++ 标准库中的栈库头文件,提供了栈容器的功能。

1. 头文件

#include<bitset>

2.声明

stack<T> stk		//声明一个存储类型为T的栈 

3.常用函数

函数描述参数
stk.push(val)在栈顶插入元素valval: 要插入的元素
stk.pop()删除栈顶的元素
stk.top()返回栈顶的元素
stk.empty()判断栈是否为空,如果栈为空返回true,否则返回false
stk.size()返回栈中元素的个数
stk.swap(stk2)交换两个栈的内容stk2: 要交换内容的另一个栈

十一、#include< cstring >

常用函数

当使用cstring头文件时,主要包含了C语言风格的字符串处理函数。

下面是cstring头文件中常用的函数:

函数描述参数
strlen(str)计算字符串的长度str: 指向以空字符结尾的字符串的指针
strcpy(dest, src)复制一个字符串dest: 目标字符串指针,src: 源字符串指针
strncpy(dest, src, n)复制指定长度的字符串dest: 目标字符串指针,src: 源字符串指针,n: 复制的字符个数
strcmp(str1, str2)比较两个字符串str1: 字符串1指针,str2: 字符串2指针
strncmp(str1, str2, n)按指定长度比较两个字符串str1: 字符串1指针,str2: 字符串2指针,n: 比较的字符个数
strcat(dest, src)连接两个字符串dest: 目标字符串指针,src: 源字符串指针
strncat(dest, src, n)连接指定长度的字符串dest: 目标字符串指针,src: 源字符串指针,n: 连接的字符个数
strstr(str, substr)在字符串中查找子串,并返回第一次出现的位置str: 字符串指针,substr: 子串指针
strchr(str, ch)在字符串中查找指定字符,并返回第一次出现的位置str: 字符串指针,ch: 要查找的字符
strrchr(str, ch)在字符串中查找指定字符,并返回最后一次出现的位置str: 字符串指针,ch: 要查找的字符
memset(ptr, value, size)将内存区域设置为指定的值ptr: 内存区域的指针,value: 要设置的值,size: 内存区域的大小
memcpy(dest, src, size)将内存区域从源位置复制到目标位置dest: 目标内存区域指针,src: 源内存区域指针,size: 复制的大小
memmove(dest, src, size)将内存区域从源位置复制到目标位置,处理重叠区域dest: 目标内存区域指针,src: 源内存区域指针,size: 复制的大小

cstring头文件中的这些函数用于对C风格的字符串进行处理,C风格的字符串是以空字符结尾的字符数组,因此可以使用这些函数来计算字符串的长度、复制、比较、连接等操作。在算法比赛中,如果需要对字符串进行处理,可以使用这些函数来方便地完成相关操作。

一个重要的函数memset

函数声明:

void* memset(void* ptr, int value, size_t num);

参数说明:

  • ptr:指向要设置的内存块的起始地址的指针。
  • value:要设置的值,通常是一个整数(0~255)。
  • num:要设置的字节数。
    函数返回值:
  • 返回指向ptr的指针。

memset函数主要用于对一段内存块进行初始化,常见的用法是将数组或结构体清零。注意,memset函数设置的是字节级别的值,而不是直接对数组元素进行赋值。因此,如果要初始化一个数组,其中的元素类型是非字符类型(如整数、浮点数等),则需要使用适当的类型转换。

例如,将整个数组初始化为0和无穷大(最为常用):

#include <cstring>
#include <iostream>
int main() {
    int arr[5];
    memset(arr, 0, sizeof(arr)); // 将整个数组初始化为0
    memset(arr, 0x3f, sizeof(arr))// 将整个数组初始化为无穷大,数组的每个元素为0x3f3f3f3f=1061109567 0x3f=63 
    return 0;
}

需要注意的是,memset函数逐字节地设置内存块的值,因此只适用于简单数据类型的初始化。

十二、#include< algorithm >

常用函数

<algorithm> 是 C++ 标准库中的一个头文件,其中包含了许多常用的算法函数。下面是 <algorithm> 头文件中一些常用的函数:

函数描述参数
sort(first, last)对指定范围内的元素进行排序first: 指向要排序范围的起始位置的迭代器,last: 指向要排序范围的末尾位置的迭代器
sort(first, last, comp)对指定范围内的元素进行排序,使用自定义的比较函数first: 指向要排序范围的起始位置的迭代器,last: 指向要排序范围的末尾位置的迭代器,comp: 比较函数
reverse(first, last)反转指定范围内的元素first: 指向要反转范围的起始位置的迭代器,last: 指向要反转范围的末尾位置的迭代器
min(a, b)返回两个元素中的较小值a: 第一个元素,b: 第二个元素
max(a, b)返回两个元素中的较大值a: 第一个元素,b: 第二个元素
lower_bound(first, last, val) (二分查找)在已排序范围内查找第一个不小于指定值的元素,并返回其位置的迭代器first: 指向已排序范围的起始位置的迭代器,last: 指向已排序范围的末尾位置的迭代器,val: 要查找的值 (需要确保范围是有序的)
upper_bound(first, last, val) (二分查找)在已排序范围内查找第一个大于指定值的元素,并返回其位置的迭代器first: 指向已排序范围的起始位置的迭代器,last: 指向已排序范围的末尾位置的迭代器,val: 要查找的值 (需要确保范围是有序的)
min_element(first, last)返回范围内的最小元素的迭代器first: 指向要查找范围的起始位置的迭代器,last: 指向要查找范围的末尾位置的迭代器
max_element(first, last)返回范围内的最大元素的迭代器first: 指向要查找范围的起始位置的迭代器,last: 指向要查找范围的末尾位置的迭代器
count(first, last, val)统计范围内等于指定值的元素个数first: 指向要统计范围的起始位置的迭代器,last: 指向要统计范围的末尾位置的迭代器,val: 要统计的值
find(first, last, val)在范围内查找指定值,并返回第一次出现的位置的迭代器first: 指向要查找范围的起始位置的迭代器,last: 指向要查找范围的末尾位置的迭代器,val: 要查找的值

十三、#include< cmath >

<math> 是 C++ 标准库中的数学库头文件,提供了许多数学函数和常量。

常用函数

下面是 <cmath> 头文件中常用的数学函数及其作用的表格:

函数描述
abs(x)返回 x 的绝对值。
sqrt(x)返回 x 的平方根。
pow(x, y)返回 xy 次幂。
exp(x)返回 e 的 x 次幂(e 是自然对数的底数,约等于2.71828)。
log(x)返回 x 的自然对数(以 e 为底)。
log10(x)返回 x 的以 10 为底的对数。
sin(x)返回 x 的正弦值(x 为弧度)。
cos(x)返回 x 的余弦值(x 为弧度)。
tan(x)返回 x 的正切值(x 为弧度)。
asin(x)返回 x 的反正弦值(返回值范围在 -pi/2pi/2 之间,x 为弧度)。
acos(x)返回 x 的反余弦值(返回值范围在 0pi 之间,x 为弧度)。
atan(x)返回 x 的反正切值(返回值范围在 -pi/2pi/2 之间,x 为弧度)。
atan2(y, x)返回点 (x, y) 的反正切值(返回值范围在 -pipi 之间,坐标系中的 xy 均为浮点数)。
ceil(x)返回不小于 x 的最小整数(向上取整)。
floor(x)返回不大于 x 的最大整数(向下取整)。
round(x)返回最接近 x 的整数(四舍五入取整)。
min(x, y)返回 xy 中的较小值。
max(x, y)返回 xy 中的较大值。

十四、#include< cctype >

这些函数在算法比赛中常用于处理输入数据,特别是对字符进行判断和转换。通过使用这些函数,我们可以更加方便地处理输入数据,从而使算法的实现更加简洁和高效。

常用函数

函数描述
isalpha(c)检查字符 c 是否是字母。
isdigit(c)检查字符 c 是否是数字。
isalnum(c)检查字符 c 是否是字母或数字。
isspace(c)检查字符 c 是否是空白字符(空格、制表符、换行符等)。
tolower(c)将字符 c 转换为小写字母。
toupper(c)将字符 c 转换为大写字母。

十五、#include< string >

在算法比赛中,常常需要对字符串进行各种操作,比如查找子串、拼接字符串、插入子串、删除子串等。以上列出的函数是在比赛中经常用到的一些字符串操作函数,掌握它们可以帮助我们高效地处理字符串数据。需要特别注意的是,C++ 中的 string 类型是动态大小的字符串类型, 头文件中的函数操作的是 string 类型对象,而不是字符数组。在使用这些函数时不需要担心数组越界等问题。可以根据需要动态调整大小,因此可以方便地进行各种字符串操作。

常用函数

函数描述
str.size()返回字符串 str 的长度。
str.empty()判断字符串 str 是否为空,如果字符串为空返回 true,否则返回 false
str.clear()清空字符串 str 中的内容。
str.substr(pos, len)返回从位置 pos 开始的长度为 len 的子串,如果未指定 len,则返回从位置 pos 开始的全部子串。
str.find(sub, pos)在字符串 str 中从位置 pos 开始查找子串 sub,返回第一次出现子串的位置,如果未找到则返回 string::npos
str.append(sub)将字符串 sub 追加到字符串 str 的末尾。
str.insert(pos, sub)在字符串 str 的位置 pos 插入子串 sub
str.erase(pos, len)从字符串 str 中删除从位置 pos 开始的长度为 len 的子串。
str.replace(pos, len, sub)用子串 sub 替换字符串 str 中从位置 pos 开始的长度为 len 的子串。

总结

以上就是今天要讲的内容,本文仅仅简单介绍了本系列文章介绍了在算法比赛中常用的STL容器以及相关函数。希望可以对您的对于提高编程效率提供帮助。

由于笔者能力有限,此篇文章定有不足之处,欢迎指正。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值