C++ 算法题常用函数整理(自我完善版)
C++ 算法题常用函数整理(自我完善版)
说明:本文档将之前笔记中的常用函数与后续自己完善补充的函数合并整理。每个函数尽量按照“作用—头文件—使用格式—示例—注意项”的形式记录,方便做算法题时快速查阅。
一、初始化与赋值类函数
1. memset
作用
快速把数组或结构体的一段内存初始化成某个值。
头文件
#include <cstring>
使用万能头文件时:
#include <bits/stdc++.h>
可以不用单独写。
使用格式
memset(数组名, 填充值, sizeof(数组名));
常见用法
int a[100];
memset(a, 0, sizeof(a)); // 全部初始化为 0
memset(a, -1, sizeof(a)); // 全部初始化为 -1
二维数组用法
int a[105][105];
memset(a, 0, sizeof(a));
注意项
memset 是按字节赋值的,所以一般只推荐初始化为:
0
-1
不要这样写:
memset(a, 999999, sizeof(a)); // 错误用法
如果要初始化成 999999、1e9 这类较大值,应该使用 fill()。
2. fill
作用
把一段范围内的元素全部赋成同一个值。
头文件
#include <algorithm>
使用格式
fill(起始位置, 结束位置, 填充值);
一维数组用法
int a[100];
fill(a, a + 100, 999999);
表示把 a[0] 到 a[99] 全部赋值为 999999。
二维数组用法
int a[105][105];
fill(a[0], a[0] + 105 * 105, 999999);
vector 用法
vector<int> v(10);
fill(v.begin(), v.end(), 5);
注意项
fill() 是按元素赋值,适合初始化成任意值。
如果初始化为 0 或 -1,可以用 memset。
如果初始化为其他值,优先用 fill。
二、统计、查找、最值类函数
3. count
作用
统计某个值在一段范围内出现的次数。
头文件
#include <algorithm>
使用格式
count(起始位置, 结束位置, 要统计的值);
范围是:
[起始位置, 结束位置)
也就是包含起始位置,不包含结束位置。
数组用法
int a[6] = {1, 2, 2, 3, 2, 4};
int ans = count(a, a + 6, 2);
cout << ans << endl;
输出:
3
vector 用法
vector<int> v = {1, 2, 2, 3, 2, 4};
int ans = count(v.begin(), v.end(), 2);
string 用法
string s = "banana";
int ans = count(s.begin(), s.end(), 'a');
输出:
3
注意项
vector、数组、string 本身没有 .count() 成员函数。
不能写:
v.count(2); // 错误
应该写:
count(v.begin(), v.end(), 2);
但是 set、map、unordered_set、unordered_map 有自己的 .count() 成员函数。
4. max_element
作用
找到一段范围中的最大值。
头文件
#include <algorithm>
使用格式
max_element(起始位置, 结束位置);
数组求最大值
int a[5] = {3, 1, 7, 2, 5};
int mx = *max_element(a, a + 5);
cout << mx << endl;
输出:
7
数组求最大值下标
int pos = max_element(a, a + 5) - a;
vector 求最大值
vector<int> v = {3, 1, 7, 2, 5};
int mx = *max_element(v.begin(), v.end());
vector 求最大值下标
int pos = max_element(v.begin(), v.end()) - v.begin();
注意项
max_element() 返回的是最大值的位置,不是最大值本身。
所以求最大值要加 *:
*max_element(a, a + n);
如果有多个最大值,返回第一个最大值的位置。
5. min_element
作用
找到一段范围中的最小值。
头文件
#include <algorithm>
使用格式
min_element(起始位置, 结束位置);
数组求最小值
int a[5] = {3, 1, 7, 2, 5};
int mn = *min_element(a, a + 5);
数组求最小值下标
int pos = min_element(a, a + 5) - a;
vector 求最小值
vector<int> v = {3, 1, 7, 2, 5};
int mn = *min_element(v.begin(), v.end());
vector 求最小值下标
int pos = min_element(v.begin(), v.end()) - v.begin();
注意项
和 max_element() 一样,min_element() 返回的是位置。
要取值必须加 *。
6. find
作用
在一段范围内查找某个值是否存在。
头文件
#include <algorithm>
使用格式
find(起始位置, 结束位置, 要查找的值);
数组用法
int a[5] = {1, 3, 5, 7, 9};
int *p = find(a, a + 5, 5);
if(p != a + 5){
cout << "找到了";
}else{
cout << "没找到";
}
数组中查找下标
int pos = p - a;
vector 用法
vector<int> v = {1, 3, 5, 7, 9};
auto it = find(v.begin(), v.end(), 5);
if(it != v.end()){
cout << "找到了";
}
vector 中查找下标
int pos = it - v.begin();
注意项
find() 如果没有找到,会返回结束位置。
数组中没有找到时返回:
a + n
vector 中没有找到时返回:
v.end()
所以必须先判断是否找到,再取下标。
7. binary_search
作用
判断某个值是否存在。
头文件
#include <algorithm>
使用格式
binary_search(起始位置, 结束位置, 要查找的值);
返回值是 true 或 false。
示例
vector<int> v = {1, 3, 5, 7, 9};
if(binary_search(v.begin(), v.end(), 5)){
cout << "存在";
}else{
cout << "不存在";
}
注意项
使用 binary_search() 前,序列必须有序。
通常需要先写:
sort(v.begin(), v.end());
binary_search() 只能判断是否存在,不能返回位置。
如果要找位置,可以用 lower_bound()。
8. lower_bound
作用
在有序序列中,找到第一个大于等于某个值的位置。
头文件
#include <algorithm>
使用格式
lower_bound(起始位置, 结束位置, 要查找的值);
示例
vector<int> v = {1, 3, 3, 5, 7};
auto it = lower_bound(v.begin(), v.end(), 3);
cout << it - v.begin() << endl;
输出:
1
第一个大于等于 3 的位置是 v[1]。
数组用法
int a[5] = {1, 3, 3, 5, 7};
int pos = lower_bound(a, a + 5, 3) - a;
注意项
使用前必须保证序列有序。
如果所有元素都小于要查找的值,会返回结束位置。
例如:
auto it = lower_bound(v.begin(), v.end(), 100);
此时:
it == v.end()
9. upper_bound
作用
在有序序列中,找到第一个大于某个值的位置。
头文件
#include <algorithm>
使用格式
upper_bound(起始位置, 结束位置, 要查找的值);
示例
vector<int> v = {1, 3, 3, 5, 7};
auto it = upper_bound(v.begin(), v.end(), 3);
cout << it - v.begin() << endl;
输出:
3
第一个大于 3 的位置是 v[3]。
注意项
lower_bound 找的是:
>= x
upper_bound 找的是:
> x
二者都要求序列有序。
三、求和、数学运算类函数
10. accumulate
作用
求一段范围内所有元素的和。
头文件
#include <numeric>
使用格式
accumulate(起始位置, 结束位置, 初始值);
第三个参数是“初始值”。
vector 求和
vector<int> v = {1, 2, 3, 4, 5};
int sum = accumulate(v.begin(), v.end(), 0);
这里的 0 表示从 0 开始累加。
实际计算过程相当于:
0 + 1 + 2 + 3 + 4 + 5
数组求和
int a[5] = {1, 2, 3, 4, 5};
int sum = accumulate(a, a + 5, 0);
初始值不是 0 的情况
vector<int> v = {1, 2, 3};
int sum = accumulate(v.begin(), v.end(), 10);
结果是:
10 + 1 + 2 + 3 = 16
long long 求和
vector<int> v = {1000000000, 1000000000, 1000000000};
long long sum = accumulate(v.begin(), v.end(), 0LL);
注意项
如果结果可能超过 int 范围,第三个参数要写成:
0LL
不要写:
long long sum = accumulate(v.begin(), v.end(), 0);
因为第三个参数 0 是 int 类型,中间过程可能按照 int 计算,导致溢出。
11. abs
作用
求绝对值。
头文件
#include <cstdlib>
#include <cmath>
使用万能头文件时不用单独写。
使用格式
abs(x);
示例
int x = -5;
cout << abs(x) << endl;
输出:
5
long long 用法
long long x = -10000000000LL;
cout << llabs(x) << endl;
注意项
如果变量是 long long,可以用 llabs(),也可以在多数情况下使用 abs()。
但为了更清楚,处理 long long 时建议写:
llabs(x);
12. sqrt
作用
求平方根。
头文件
#include <cmath>
使用格式
sqrt(x);
示例
double x = sqrt(16);
cout << x << endl;
输出:
4
注意项
sqrt() 的返回值是 double 类型。
如果要判断一个整数是不是完全平方数,不建议直接写:
if(sqrt(x) * sqrt(x) == x)
更稳妥写法:
long long t = sqrt(x);
if(t * t == x){
cout << "是完全平方数";
}
13. pow
作用
求幂。
头文件
#include <cmath>
使用格式
pow(a, b);
表示求:
a 的 b 次方
示例
double x = pow(2, 3);
cout << x << endl;
输出:
8
注意项
pow() 返回值是 double,可能有精度误差。
如果是整数幂,尤其是算法题中需要准确整数结果时,尽量自己循环乘,或者写快速幂。
例如:
long long ans = 1;
for(int i=1;i<=3;i++){
ans *= 2;
}
14. exp
作用
求自然常数 e 的 x 次方。
头文件
#include <cmath>
使用格式
exp(x);
示例
double x = exp(1);
cout << x << endl;
输出接近:
2.71828
注意项
exp() 返回值是 double。
算法竞赛中较少用于整数题,主要用于数学计算题。
15. ceil
作用
向上取整。
头文件
#include <cmath>
使用格式
ceil(x);
示例
double x = 3.2;
cout << ceil(x) << endl;
输出:
4
注意项
ceil() 返回值是 double。
如果要用整数接收:
int ans = ceil(x);
需要注意浮点数精度问题。
16. floor
作用
向下取整。
头文件
#include <cmath>
使用格式
floor(x);
示例
double x = 3.8;
cout << floor(x) << endl;
输出:
3
注意项
floor() 返回值是 double。
17. round
作用
四舍五入。
头文件
#include <cmath>
使用格式
round(x);
示例
double x = 3.6;
cout << round(x) << endl;
输出:
4
注意项
round() 返回值是 double。
如果题目要求保留小数位,通常不要用 round(),而是使用输出格式控制:
cout << fixed << setprecision(2) << x;
18. fmod
作用
求两个浮点数相除后的余数。
头文件
#include <cmath>
使用格式
fmod(x, y);
示例
double x = 7.5;
double y = 2.0;
cout << fmod(x, y) << endl;
输出:
1.5
注意项
整数取余用 %:
7 % 2
浮点数取余用 fmod():
fmod(7.5, 2.0)
19. modf
作用
把一个浮点数拆成整数部分和小数部分。
头文件
#include <cmath>
使用格式
modf(x, &整数部分变量);
示例
double x = 3.14;
double intpart;
double frac = modf(x, &intpart);
cout << intpart << endl; // 3
cout << frac << endl; // 0.14
注意项
第二个参数要传地址,所以要写:
&intpart
不能直接写:
modf(x, intpart); // 错误
20. __gcd / gcd
作用
求两个数的最大公约数。
头文件
__gcd:
#include <algorithm>
gcd:
#include <numeric>
使用格式
__gcd(a, b);
gcd(a, b);
示例
int a = 12, b = 18;
cout << __gcd(a, b) << endl;
输出:
6
注意项
__gcd 是 GCC 常用写法。
gcd 是 C++17 标准写法。
如果 OJ 使用 C++14,可能不能用 gcd(),这时用:
__gcd(a, b)
21. lcm
作用
求两个数的最小公倍数。
头文件
#include <numeric>
使用格式
lcm(a, b);
示例
int a = 12, b = 18;
cout << lcm(a, b) << endl;
输出:
36
手写写法
如果 OJ 不支持 lcm(),可以写:
int ans = a / __gcd(a, b) * b;
注意项
为了减少溢出风险,建议先除再乘:
a / __gcd(a, b) * b
不要写成:
a * b / __gcd(a, b)
四、排序、翻转、去重、排列类函数
22. sort
作用
排序。
头文件
#include <algorithm>
使用格式
sort(起始位置, 结束位置);
默认从小到大排序。
数组排序
int a[5] = {3, 1, 5, 2, 4};
sort(a, a + 5);
排序后:
1 2 3 4 5
vector 排序
vector<int> v = {3, 1, 5, 2, 4};
sort(v.begin(), v.end());
从大到小排序
sort(v.begin(), v.end(), greater<int>());
自定义排序
bool cmp(int a, int b){
return a > b;
}
sort(v.begin(), v.end(), cmp);
注意项
排序范围仍然是左闭右开。
数组 a 有 n 个元素:
sort(a, a + n);
不要写成:
sort(a, a + n - 1); // 会漏掉最后一个元素
23. reverse
作用
翻转一段范围内的元素。
头文件
#include <algorithm>
使用格式
reverse(起始位置, 结束位置);
数组翻转
int a[5] = {1, 2, 3, 4, 5};
reverse(a, a + 5);
翻转后:
5 4 3 2 1
vector 翻转
vector<int> v = {1, 2, 3, 4, 5};
reverse(v.begin(), v.end());
string 翻转
string s = "abcde";
reverse(s.begin(), s.end());
cout << s << endl;
输出:
edcba
注意项
reverse() 也是左闭右开区间。
如果只想翻转一部分,要注意下标范围。
24. unique
作用
去掉相邻重复元素。
头文件
#include <algorithm>
使用格式
unique(起始位置, 结束位置);
vector 去重常用写法
vector<int> v = {1, 3, 3, 2, 2, 5};
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
去重后:
1 2 3 5
注意项
unique() 只去除相邻重复元素。
所以要对整个序列去重,一般先排序:
sort(v.begin(), v.end());
单独写:
unique(v.begin(), v.end());
并不会真正改变 vector 的长度。
要配合:
erase()
25. next_permutation
作用
生成当前序列的下一个排列。
头文件
#include <algorithm>
使用格式
next_permutation(起始位置, 结束位置);
返回值是 true 或 false。
输出所有排列
vector<int> v = {1, 2, 3};
sort(v.begin(), v.end());
do{
for(int x : v){
cout << x << " ";
}
cout << endl;
}while(next_permutation(v.begin(), v.end()));
输出:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
注意项
如果想输出所有排列,最好先排序。
如果一开始不是最小字典序,可能会漏掉前面的排列。
26. prev_permutation
作用
生成当前序列的上一个排列。
头文件
#include <algorithm>
使用格式
prev_permutation(起始位置, 结束位置);
示例
vector<int> v = {3, 2, 1};
do{
for(int x : v){
cout << x << " ";
}
cout << endl;
}while(prev_permutation(v.begin(), v.end()));
注意项
next_permutation() 是按字典序从小到大生成。
prev_permutation() 是按字典序从大到小生成。
27. swap
作用
交换两个变量的值。
头文件
#include <utility>
通常 <algorithm> 或 <bits/stdc++.h> 中也包含它。
使用格式
swap(a, b);
示例
int a = 3, b = 5;
swap(a, b);
cout << a << " " << b << endl;
输出:
5 3
数组元素交换
swap(a[i], a[j]);
注意项
swap() 可以交换普通变量、数组元素、vector 元素、pair 等。
五、字符串常用函数
28. string 定义与基本操作
作用
字符串类型,比字符数组更方便。
头文件
#include <string>
定义
string s;
string s1 = "hello";
string s2(5, 'a');
其中:
string s2(5, 'a');
表示生成一个字符串:
aaaaa
常用操作
s.size(); // 字符串长度
s.length(); // 字符串长度
s.empty(); // 判断是否为空
s.clear(); // 清空字符串
s[i]; // 访问第 i 个字符
示例
string s = "hello";
cout << s.size() << endl;
cout << s[0] << endl;
输出:
5
h
注意项
string 下标从 0 开始。
访问时不要越界。
29. substr
作用
截取字符串的一部分。
头文件
#include <string>
使用格式
s.substr(起始下标, 截取长度);
示例
string s = "abcdef";
string t = s.substr(1, 3);
cout << t << endl;
输出:
bcd
解释:
从下标 1 开始,截取 3 个字符。
只写起始下标
string s = "abcdef";
string t = s.substr(2);
cout << t << endl;
输出:
cdef
注意项
substr(pos, len) 中:
pos
是起始位置。
len
是截取长度,不是结束下标。
30. string::find
作用
在字符串中查找某个字符或子串。
头文件
#include <string>
使用格式
s.find(要查找的内容);
查找字符
string s = "hello";
int pos = s.find('e');
cout << pos << endl;
输出:
1
查找子串
string s = "hello world";
int pos = s.find("world");
cout << pos << endl;
输出:
6
判断是否找到
if(s.find("abc") != string::npos){
cout << "找到了";
}else{
cout << "没找到";
}
注意项
如果找不到,返回:
string::npos
不要直接判断:
if(s.find("abc")) // 容易出错
因为如果查找的内容在下标 0,返回值是 0,会被当成 false。
正确写法:
if(s.find("abc") != string::npos)
31. c_str
作用
把 string 转换成 C 风格字符串。
头文件
#include <string>
使用格式
s.c_str();
示例
string s = "hello";
printf("%s\n", s.c_str());
注意项
printf 不能直接输出 string。
错误写法:
printf("%s\n", s); // 错误
正确写法:
printf("%s\n", s.c_str());
如果使用 cout,可以直接输出:
cout << s;
32. stoi
作用
把字符串转换成整数。
头文件
#include <string>
使用格式
stoi(字符串);
示例
string s = "123";
int x = stoi(s);
cout << x + 1 << endl;
输出:
124
注意项
字符串必须能转换成数字。
string s = "abc";
int x = stoi(s); // 会出错
33. stol / stoll
作用
把字符串转换成长整型。
头文件
#include <string>
使用格式
stol(字符串);
stoll(字符串);
示例
string s = "12345678900";
long long x = stoll(s);
cout << x << endl;
注意项
如果数字可能超过 int 范围,要用 stoll(),不要用 stoi()。
34. stof / stod
作用
把字符串转换成浮点数。
头文件
#include <string>
使用格式
stof(字符串);
stod(字符串);
示例
string s = "3.14";
double x = stod(s);
cout << x << endl;
注意项
stof() 转成 float。
stod() 转成 double。
35. to_string
作用
把数字转换成字符串。
头文件
#include <string>
使用格式
to_string(数字);
示例
int x = 123;
string s = to_string(x);
cout << s << endl;
输出:
123
注意项
to_string() 转换后的结果是字符串,不是数字。
六、字符判断与转换函数
36. isdigit
作用
判断一个字符是否是数字字符。
头文件
#include <cctype>
使用格式
isdigit(字符);
示例
char c = '8';
if(isdigit(c)){
cout << "是数字";
}
注意项
isdigit() 判断的是字符。
isdigit('8')
是正确的。
不要把整数 8 当成字符使用。
37. isalpha
作用
判断一个字符是否是字母。
头文件
#include <cctype>
使用格式
isalpha(字符);
示例
char c = 'A';
if(isalpha(c)){
cout << "是字母";
}
38. isalnum
作用
判断一个字符是否是字母或数字。
头文件
#include <cctype>
使用格式
isalnum(字符);
示例
char c = '7';
if(isalnum(c)){
cout << "是字母或数字";
}
39. islower
作用
判断一个字符是否是小写字母。
头文件
#include <cctype>
使用格式
islower(字符);
示例
char c = 'a';
if(islower(c)){
cout << "是小写字母";
}
40. isupper
作用
判断一个字符是否是大写字母。
头文件
#include <cctype>
使用格式
isupper(字符);
示例
char c = 'A';
if(isupper(c)){
cout << "是大写字母";
}
41. tolower
作用
把大写字母转换成小写字母。
头文件
#include <cctype>
使用格式
tolower(字符);
示例
char c = 'A';
c = tolower(c);
cout << c << endl;
输出:
a
42. toupper
作用
把小写字母转换成大写字母。
头文件
#include <cctype>
使用格式
toupper(字符);
示例
char c = 'a';
c = toupper(c);
cout << c << endl;
输出:
A
43. 字符与数字之间的转换
作用
处理字符串中的数字字符。
字符转数字
char c = '7';
int x = c - '0';
cout << x << endl;
输出:
7
数字转字符
int x = 7;
char c = x + '0';
cout << c << endl;
输出:
7
注意项
字符 '7' 和整数 7 不一样。
字符转数字常用:
c - '0'
数字转字符常用:
x + '0'
只适合 0 到 9 的单个数字。
七、二进制相关函数
44. __builtin_popcount
作用
统计一个整数的二进制表示中有多少个 1。
头文件
GCC 内置函数,使用:
#include <bits/stdc++.h>
即可。
使用格式
__builtin_popcount(x);
示例
int x = 7;
cout << __builtin_popcount(x) << endl;
输出:
3
因为 7 的二进制是:
111
有三个 1。
注意项
__builtin_popcount() 适用于 int 类型。
如果是 long long,要用:
__builtin_popcountll(x);
45. __builtin_popcountll
作用
统计 long long 整数的二进制表示中有多少个 1。
头文件
GCC 内置函数,使用:
#include <bits/stdc++.h>
即可。
使用格式
__builtin_popcountll(x);
示例
long long x = 15;
cout << __builtin_popcountll(x) << endl;
输出:
4
八、随机数函数
46. rand
作用
生成一个随机整数。
头文件
#include <cstdlib>
使用格式
rand();
示例
int x = rand();
cout << x << endl;
生成 1 到 100 的随机数
int x = rand() % 100 + 1;
注意项
rand() 的随机范围通常是:
0 到 RAND_MAX
如果不设置随机种子,每次运行结果可能一样。
47. srand
作用
设置随机数种子。
头文件
#include <cstdlib>
#include <ctime>
使用格式
srand(time(0));
示例
srand(time(0));
int x = rand() % 100 + 1;
注意项
srand(time(0)) 一般只在程序开头写一次。
不要在循环中反复写。
九、常用 STL 容器
48. vector
作用
动态数组。
头文件
#include <vector>
定义
vector<int> v;
vector<int> v(10);
vector<int> v(10, 5);
其中:
vector<int> v(10, 5);
表示创建 10 个元素,每个元素都是 5。
常用函数
v.push_back(x); // 在末尾加入元素
v.pop_back(); // 删除最后一个元素
v.size(); // 元素个数
v.empty(); // 判断是否为空
v.clear(); // 清空
v.front(); // 第一个元素
v.back(); // 最后一个元素
访问元素
v[i];
注意项
vector 下标从 0 开始。
使用 v[i] 时不要越界。
49. pair
作用
存储两个相关的值,常用于存坐标、编号和权值。
头文件
#include <utility>
定义
pair<int,int> p;
赋值
p = {3, 5};
或者:
p = make_pair(3, 5);
访问
cout << p.first << " " << p.second << endl;
存坐标
pair<int,int> point = {2, 4};
可以理解为:
point.first // x 坐标
point.second // y 坐标
注意项
pair 默认先比较 first,如果 first 相同,再比较 second。
50. set
作用
集合,自动去重,并且默认从小到大排序。
头文件
#include <set>
定义
set<int> s;
常用函数
s.insert(x); // 插入元素
s.count(x); // 判断元素是否存在
s.erase(x); // 删除元素
s.size(); // 元素个数
s.empty(); // 判断是否为空
s.clear(); // 清空
示例
set<int> s;
s.insert(3);
s.insert(5);
s.insert(3);
cout << s.size() << endl;
输出:
2
注意项
对于 set 来说,count() 返回值只有:
0 // 不存在
1 // 存在
set 会自动排序,但插入和查找的速度比 unordered_set 略慢。
51. unordered_set
作用
哈希集合,常用于快速判断某个元素是否存在。
头文件
#include <unordered_set>
定义
unordered_set<int> s;
常用函数
s.insert(x); // 插入
s.count(x); // 判断是否存在
s.erase(x); // 删除
s.size(); // 元素个数
示例
unordered_set<int> s;
s.insert(3);
s.insert(5);
if(s.count(3)){
cout << "存在";
}
注意项
unordered_set 不自动排序。
一般查找更快,但不能按顺序遍历。
如果需要有序,使用 set。
52. map
作用
存储键值对。
可以理解为:
键 -> 值
头文件
#include <map>
定义
map<string, int> mp;
插入或修改
mp["Tom"] = 90;
mp["Jack"] = 85;
访问
cout << mp["Tom"] << endl;
判断键是否存在
if(mp.count("Tom")){
cout << "Tom 存在";
}
遍历
for(auto x : mp){
cout << x.first << " " << x.second << endl;
}
注意项
map 的 count() 查的是键,不是值。
如果直接访问一个不存在的键:
cout << mp["Amy"];
这个键会被自动创建,值默认为 0。
如果只是判断是否存在,建议用:
mp.count("Amy")
53. unordered_map
作用
哈希表,也用于存储键值对。
头文件
#include <unordered_map>
定义
unordered_map<string, int> mp;
示例
unordered_map<string, int> mp;
mp["Tom"] = 90;
mp["Jack"] = 85;
cout << mp["Tom"] << endl;
判断键是否存在
if(mp.count("Tom")){
cout << "存在";
}
遍历
for(auto x : mp){
cout << x.first << " " << x.second << endl;
}
注意项
map 会按照键自动排序。
unordered_map 不排序,但通常查找更快。
如果题目要求按字典序或升序输出键,使用 map 更方便。
54. queue
作用
队列,先进先出。
头文件
#include <queue>
定义
queue<int> q;
常用函数
q.push(x); // 入队
q.front(); // 访问队首元素
q.back(); // 访问队尾元素
q.pop(); // 删除队首元素
q.empty(); // 判断队列是否为空
q.size(); // 元素个数
示例
queue<int> q;
q.push(1);
q.push(2);
q.push(3);
cout << q.front() << endl;
q.pop();
cout << q.front() << endl;
输出:
1
2
注意项
pop() 只删除元素,不返回元素。
如果要使用队首元素,要先:
q.front();
再:
q.pop();
55. stack
作用
栈,后进先出。
头文件
#include <stack>
定义
stack<int> s;
常用函数
s.push(x); // 入栈
s.top(); // 访问栈顶元素
s.pop(); // 删除栈顶元素
s.empty(); // 判断是否为空
s.size(); // 元素个数
示例
stack<int> s;
s.push(1);
s.push(2);
s.push(3);
cout << s.top() << endl;
s.pop();
cout << s.top() << endl;
输出:
3
2
注意项
pop() 只删除元素,不返回元素。
56. priority_queue
作用
优先队列,可以快速取出当前最大值或最小值。
头文件
#include <queue>
默认大根堆
priority_queue<int> q;
默认堆顶是最大值。
示例
priority_queue<int> q;
q.push(3);
q.push(5);
q.push(1);
cout << q.top() << endl;
输出:
5
常用函数
q.push(x); // 插入元素
q.top(); // 访问堆顶元素
q.pop(); // 删除堆顶元素
q.empty(); // 判断是否为空
q.size(); // 元素个数
小根堆写法
priority_queue<int, vector<int>, greater<int>> q;
示例:
priority_queue<int, vector<int>, greater<int>> q;
q.push(3);
q.push(5);
q.push(1);
cout << q.top() << endl;
输出:
1
注意项
priority_queue 默认是大根堆。
小根堆写法比较长,要记住:
priority_queue<int, vector<int>, greater<int>> q;
十、常用输出格式控制
57. fixed 和 setprecision
作用
控制小数输出位数。
头文件
#include <iomanip>
使用格式
cout << fixed << setprecision(位数) << 变量;
示例
double x = 3.1415926;
cout << fixed << setprecision(2) << x << endl;
输出:
3.14
注意项
setprecision(2) 单独使用时表示有效数字位数。
如果配合 fixed,表示小数点后保留几位。
常用写法:
cout << fixed << setprecision(2) << x;
十一、常用速查
数组常用写法
sort(a, a + n); // 排序
reverse(a, a + n); // 翻转
fill(a, a + n, 0); // 填充
count(a, a + n, x); // 统计 x 次数
find(a, a + n, x); // 查找 x
*max_element(a, a + n); // 最大值
max_element(a, a + n) - a; // 最大值下标
*min_element(a, a + n); // 最小值
min_element(a, a + n) - a; // 最小值下标
accumulate(a, a + n, 0); // 求和
lower_bound(a, a + n, x) - a; // 第一个 >= x 的位置
upper_bound(a, a + n, x) - a; // 第一个 > x 的位置
vector 常用写法
sort(v.begin(), v.end()); // 排序
reverse(v.begin(), v.end()); // 翻转
fill(v.begin(), v.end(), 0); // 填充
count(v.begin(), v.end(), x); // 统计 x 次数
find(v.begin(), v.end(), x); // 查找 x
*max_element(v.begin(), v.end()); // 最大值
max_element(v.begin(), v.end()) - v.begin(); // 最大值下标
*min_element(v.begin(), v.end()); // 最小值
min_element(v.begin(), v.end()) - v.begin(); // 最小值下标
accumulate(v.begin(), v.end(), 0); // 求和
v.erase(unique(v.begin(), v.end()), v.end()); // 去重
字符串常用写法
s.size(); // 长度
s.substr(pos, len); // 截取
s.find("abc"); // 查找
s.find("abc") != string::npos; // 判断是否找到
stoi(s); // 字符串转 int
stoll(s); // 字符串转 long long
stod(s); // 字符串转 double
to_string(x); // 数字转字符串
set / map 常用写法
set<int> s;
s.insert(x);
s.count(x);
s.erase(x);
map<string, int> mp;
mp["Tom"] = 90;
mp.count("Tom");
队列、栈、优先队列常用写法
queue<int> q;
q.push(x);
q.front();
q.pop();
stack<int> s;
s.push(x);
s.top();
s.pop();
priority_queue<int> pq;
pq.push(x);
pq.top();
pq.pop();
更多推荐
所有评论(0)