STL标准模板库
本文最后更新于:15 天前
vector, 变长数组,倍增的思想
size() 返回元素个数
empty() 返回是否为空
clear() 清空
front()/back()
push_back()/pop_back()
begin()/end()
[]
支持比较运算,按字典序
pair<int, int>
first, 第一个元素
second, 第二个元素
支持比较运算,以first为第一关键字,以second为第二关键字(字典序)
string,字符串
size()/length() 返回字符串长度
empty()
clear()
substr(起始下标,(子串长度)) 返回子串
c_str() 返回字符串所在字符数组的起始地址
queue, 队列
size()
empty()
push() 向队尾插入一个元素
front() 返回队头元素
back() 返回队尾元素
pop() 弹出队头元素
priority_queue, 优先队列,默认是大根堆
push() 插入一个元素
top() 返回堆顶元素
pop() 弹出堆顶元素
定义成小根堆的方式:priority_queue<int, vector<int>, greater<int>> q;
stack, 栈
size()
empty()
push() 向栈顶插入一个元素
top() 返回栈顶元素
pop() 弹出栈顶元素
deque, 双端队列
size()
empty()
clear()
front()/back()
push_back()/pop_back()
push_front()/pop_front()
begin()/end()
[]
set, map, multiset, multimap, 基于平衡二叉树(红黑树),动态维护有序序列
size()
empty()
clear()
begin()/end()
++, -- 返回前驱和后继,时间复杂度 O(logn)
set/multiset
insert() 插入一个数
find() 查找一个数
count() 返回某一个数的个数
erase()
(1) 输入是一个数x,删除所有x O(k + logn)
(2) 输入一个迭代器,删除这个迭代器
lower_bound()/upper_bound()
lower_bound(x) 返回大于等于x的最小的数的迭代器
upper_bound(x) 返回大于x的最小的数的迭代器
map/multimap
insert() 插入的数是一个pair
erase() 输入的参数是pair或者迭代器
find()
[] 注意multimap不支持此操作。 时间复杂度是 O(logn)
lower_bound()/upper_bound()
unordered_set, unordered_map, unordered_multiset, unordered_multimap, 哈希表
和上面类似,增删改查的时间复杂度是 O(1)
不支持 lower_bound()/upper_bound(), 迭代器的++,--
bitset, 圧位
bitset<10000> s;
~, &, |, ^
>>, <<
==, !=
[]
count() 返回有多少个1
any() 判断是否至少有一个1
none() 判断是否全为0
set() 把所有位置成1
set(k, v) 将第k位变成v
reset() 把所有位变成0
flip() 等价于~
flip(k) 把第k位取反
1. map
map 中所有元素的 key 的值必须是唯一的,multimap 则允许有重复的 Key 值。
- 构建
map<string, long long> m;
- 向 map 中插入元素
m[key]=value;
//[key]操作是map很有特色的操作,如果在map中存在键值为key的元素对, 则返回该元素对的值域部分,否则将会创建一个键值为key的元素对,值域为默认值。所以可以用该操作向map中插入元素对或修改已经存在的元素对的值域部分。
m.insert(male_pair(key,value));
//也可以直接调用insert方法插入元素对,insert操作会返回一个pair,当map中没有与key相匹配的键值时,其first是指向插入元素对的迭代器,其second为true;若map中已经存在与key相等的键值时,其first是指向该元素对的迭代器,second为false。
- 查找元素
int i=m[key];
//要注意的是,当与该键值相匹配的元素对不存在时,会创建键值为key(当另一个元素是整形时,m[key]=0)的元素对。
map<string, int>::iterator it=m.find(key);
//如果map中存在与key相匹配的键值时,find操作将返回指向该元素对的迭代器,否则,返回的迭代器等于map的end()
- 删除元素
//erase的参数可以是key或者迭代器
m.erase(key);
//删除与指定key键值相匹配的元素对,并返回被删除的元素的个数。
m.erase(it);
//删除由迭代器it所指定的元素对,并返回指向下一个元素对的迭代器。
- map 的 upper_bound/lower_bound
iterator lower_bound( const key_type &key ): 返回一个迭代器,指向键值>= key 的第一个元素。
iterator upper_bound( const key_type &key ):返回一个迭代器,指向键值> key 的第一个元素。 - 其他简单操作
m.size(); //返回元素个数
m.empty(); //判断是否为空
m.clear(); //清空所有元素
m.begin(); //返回首迭代器
m.end(); //返回尾迭代器
2. C++ queue
#include<queue>
头文件 queue 里包含了循环队列 queue 和优先队列 priority_queue
queue<int> q;
- front():返回 queue 中第一个元素的引用。如果 queue 是常量,就返回一个常引用;如果 queue 为空,返回值是未定义的。
- back():返回 queue 中最后一个元素的引用。如果 queue 是常量,就返回一个常引用;如果 queue 为空,返回值是未定义的。
- push(const T& obj):在 queue 的尾部添加一个元素的副本。这是通过调用底层容器的成员函数 push_back() 来完成的。
- push(T&& obj):以移动的方式在 queue 的尾部添加元素。这是通过调用底层容器的具有右值引用参数的成员函数 push_back()来完成的。
- pop():删除 queue 中的第一个元素。
- size():返回 queue 中元素的个数。
- empty():如果 queue 中没有元素的话,返回 true。
- emplace():用传给 emplace() 的参数调用 T 的构造函数,在 queue 的尾部生成对象。
- swap(queue
&other_q):将当前 queue 中的元素和参数 queue 中的元素交换。它们需要包含相同类型的元素。也可以调用全局函数模板 swap() 来完成同样的操作。 -
优先队列 priority_queue
priority_queue<int> q;//大根堆(堆顶值最大)
priority_queue<int,vector<int>,greater<int> > q;//小根堆(堆顶值最小)
注意 priority_queue 中储存的元素类型必须定义“小于号”(注意这里虽然是<小于号,但实际上是大于号),较大的元素会被放在堆顶。内置的 int、string 等类型已经定义过“小于号”,若使用结构体则必须重载运算符。
由于 priority_queue 是按照从大到小排序所以重载运算符时也要反过来。
1. 大根堆
重载“<”运算符
下面的 poi 结构体保存了二维平面上的编号和坐标,比较大小时,先比较横坐标,再比较纵坐标,并考虑了精度误差。
struct poi{
int id;
double x,y;
};
const double eps = 1e-8;
bool operator<(const poi &a,const poi &b){
return a.x+eps<b.x||a.x<b.x+eps&&a.y<b.y;
}
2. 小根堆
下面代码重载运算符之后定义了一个小根堆(堆顶元素值最小,其实就是从小到大排序)
struct node{
int value ;
friend bool operator < (node a , node b)
{
return a.value > b.value;
}
};
priority_queue<node> q;
//------------------------------------------------
struct node{
int value ;
bool operator < (const node &a) const
{
return value > a.value;
}
};
priority_queue<node> q;
// 成员函数
q.top(); //访问堆顶元素
q.empty(); //检查是否为空
q.size(); //返回容纳的元素数
q.push(); //插入元素,并排序
q.pop(); //删除栈顶元素
2. 懒惰删除法
如果是手写的堆是支持删除任意一个元素,而 STL 却不支持这种操作所以我们可以用懒惰删除法
懒惰删除法又称延迟删除法,是一种应对策略。当遇到删除操作时,仅在优先队列之外做一些特殊的记录,用于辨别是否堆中的元素被删除。当从堆顶取出元素时判断是否已经被删除,若是,我们重新取一个最值。换言之,元素的“删除”推迟到堆顶执行。
比如“堆优化的 Dijkstra 算法”中当某个元素首次被取出时就达到了最短路,当我们再次取出这个元素时我们不会重新进行扩展,而是使用一个 bool 数组判断“是否进行过扩展”,其本质还是懒惰删除法的应用。
#include<deque>
双端队列 deque 支持队列两端高效地插入或删除元素的连续性存储空间。与 vector 相比,deque 在头部增删元素只需要 O ( 1 ) O(1)O(1),并且 deque 像数组一样支持下标随机访问。
[] | 随机访问 O(1) |
---|---|
begin/end | deque 的头/尾迭代器 O(1) |
front/back | 队头/队尾元素 O(1) |
push_front | 从队头入队 O(1) |
push_back | 从队尾入队 O(1) |
pop_front | 从队头出队 O(1) |
pop_back | 从队尾出队 O(1) |
clear | 清空队列 O(n) |