STL 容器
vector 变长数组
包含在 < vector > 头文件中
基本思想:倍增
系统为某一程序分配空间时,所用时间与空间大小无关,只与申请次数有关。因此 vector
为保证效率,需要尽可能减少申请次数。**vector
使用倍增的思想分配空间**
vector
在定义时,先开辟一定长度的空间,当元素个数大于当前数组长度时,开一个两倍于该长度的空间,再将原数组复制进新数组
由此可知,当开辟一个长度为 n
的 vector
数组时,需进行 log2n 次开辟空间的操作,总复制次数为 n
,平均插入每个数的时间复杂度是 O(1)
定义
cpp
1 2 3 4 5 6 7 8 9 10 11
| vector<int> a;
vector<int> a(N);
vector<int> a(10, 3);
vector<string> a(10, "wangk");
vector<int> a[10];
|
操作函数
O(1):
cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| a.size();
a.empty();
a.front();
a.back();
a.push_back(x); a.emplace_back(x);
a.pop_back();
|
O(n);
cpp
1 2 3 4 5
| a.clear();
a.erase(begin, end);
|
迭代器:
cpp
- vector 还支持随机寻址。即可以使用
a[2]
访问 a 数组第 3 个元素
遍历 vector 数组
cpp
1 2 3 4 5 6 7 8 9
| for (int i = 0; i < a.size(); i ++) cout << a[i] << endl;
for (vector<int> :: iterator i = a.begin(); i != a.end(); i ++) cout << *i << endl;
for (auto x : a) cout << x << endl;
|
- vector 还支持按照字典序比较两数组,直接使用运算符比较即可
pair 二元组
定义:
cpp
1 2 3 4 5
| pair<int, string> a;
a = make_pair(10, "Hello");
a = {10, "World"};
|
操作函数
cpp
1 2 3 4 5
| a.first();
a.second();
|
- 支持比较远算,与 vector 一样是按照字典序排序,以 first 为第一关键字,以 second 为第二关键字
ps: 一些奇技淫巧
如果有三个关键字需存储,我们仅需:
cpp
1
| pair<int, pair<int, int>> a;
|
即在 p 中存入了三个整型变量
string 字符串
定义
cpp
操作函数
cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| a.size(); || a.length();
a.empty();
a.clear();
a.substr(l ,n);
a.c_str();
|
- 字符串可以支持
+
运算,使用 a + b
即可将 a 和 b 两个字符串首位拼接在一起
queue 队列
包含在 < queue > 头文件中
定义
cpp
1 2 3
| queue<int> q;
q = queue<int>();
|
操作函数
cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| a.size();
a.empty();
a.push();
a.pop();
a.front();
a.back();
|
deque 双端队列
常数和空间都极大,不建议使用
操作函数
O(1)
cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| a.size();
a.empty();
a.clear();
a.front();
a.back();
a.push_back(x);
a.pop_back();
a.push_front(x);
a.pop_front();
|
迭代器:
cpp
- deque 还支持随机寻址。即可以使用
a[2]
访问队列 a 从左往右数第 3 个元素
priorityqueue 优先队列 / 堆
具体的实现方式,可见[[2022.11.12 - 堆]]
定义
cpp
1 2 3 4 5 6 7 8 9
| priority_queue<int> heap;
heap.push(-x);
priority_queue<int, vector<int>, greater<int> > heap;
|
操作函数
cpp
1 2 3 4 5 6 7 8 9 10 11
| heap.push();
heap.pop();
heap.top();
heap.emplace(x);
|
stack 栈
定义
cpp
操作函数
cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| heap.push();
heap.pop();
heap.top();
heap.size();
a.empty();
|
set & multiset 有序集合 & 有序多重集合
操作函数
O(1)
cpp
1 2 3 4 5 6 7 8
| a.size();
a.empty();
a.clear();
|
O(log2n)
cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| a.insert(x);
a.find(x);
a.count(x);
a.erase(x);
a.lower_bound(x);
a.upper_bound(x);
|
map & multimap 映射
包含在 < map > 头文件中
定义
cpp
1 2 3 4 5
| map<string, int> a;
a["wangk"] = 1;
|
操作函数
O(1)
cpp
1 2 3 4 5 6 7 8
| a.size();
a.empty();
a.clear();
|
O(log2n)
cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| a.insert();
a.erase();
a.find();
a.lower_bound(x);
a.upper_bound(x);
|
访问与遍历
使用 a[x]
访问时,如果无法找到,则新建一个 key 为 x 的 map,val 指向 0
cpp
1 2
| for (auto x : a) cout << x.first << " " << x.second << endl;
|
注意:在遍历中无法修改 key,只能修改 value
特殊使用
cpp
1
| cout << a["wangk"] << endl;
|
输出 1
,时间复杂度为 O(log2n)
unorderedset & unorderedmap 无序集合 / 映射
unorderedmultiset & unorderedmultimap 多重无序集合 / 映射
总体操作和 set
map
等类似,操作的时间复杂度为 O(1),不支持 lower_bound()
和upper_bound()
以及 map
的特殊使用方法
注意:在初始化时会开 4 倍空间,警钟敲烂
bitset 压位
定义
cpp
操作
~
&
|
^
>>
<<
==
!=
- 取某一位
s[]
cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| s.count();
s.any();
s.none();
s.set();
s.reset();
s.set(k, v);
s.flip();
s.flip(k);
|
STL 函数
需引入 <alrorithm>
头文件
cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| min(x, y);
max(x, y);
swap(x, y);
find(begin, end, x);
count(begin, end, x);
revise(begin, end);
random_shuffle(begin, end);
unique(begin, end);
nth_element(bengin, begin + k, end, compare);
lower_bound(begin, end, x); upper_bound(begin, end, x);
next_permutation(begin, end); prev_permutation(begin, end);
|
值得注意的是,random_shuffle
自 C++14 起被弃用,C++17 起被移除。我们可以使用 shuffle
函数代替原来的 random_shuffle
。使用方法为:
cpp
1
| shuffle(v.begin(), v.end(), rng);
|
(最后一个参数传入的是使用的随机数生成器,一般情况使用以真随机数生成器 random_device 播种的梅森旋转伪随机数生成器 mt19937)。