大多重载的算法都同时有两个版本的:
- 用"=="判断元素相等,或者用"x<y,y<x"比较大小判断相等
- 多出一个类型参数"Pred"和函数形参"Pred op",通过判断表达式op(x,y)的返回值来判断x==y或者x<y。 比如有两个版本的min_element:
iterator min_element(iterator first, iterator last);
iterator min_element(iterator first, iterator last,Pred op);
复制代码
STL中的算法大致有以下7种:
需要说明的是,算法名字并不代表实际意义,可以用自己的想象力做算法名字之外的事情;同时有些非常用算法并未列出
1.不变序列算法
该类算法不修改算法所作用的容器或对象
适用于顺序容器和关联容器
时间复杂度都是O(n)
常用算法:
名称 | 说明(代码为函数模板,InIt代表迭代器,简单的不说明) |
---|---|
find | InIt find(InIt first, InIt last, const T& val); |
count | size_t count(InIt first, InIt last, const T& val); |
min | |
max | |
min_element | FwdIt min_element(FwdIt first, FwdIt last); |
max_element | FwdIt max_element(FwdIt first, FwdIt last); |
search | 查找另一区间第一次出现的位置 |
find_first_of | |
find_end | |
equal | 判断两区间是否相等 |
for_each | Fun for_each(InIt first, InIt last, Fun f); |
2.变值算法
会修改源区间或目标区间元素的值
值被修改的那个区间不可以是关联容器(关联容器会涉及到重新排序)
常用算法:
名称 | 说明(Init输入迭代器,OutIt输出迭代器) |
---|---|
for_each | |
copy | OutIt copy(InIt first, InIt last, OutIt x); |
copy_backward | |
transform | OutIt transform(InIt first, InIt last, OutIt x, Unop uop); |
swap_ranges | |
fill | |
fill_n | |
generate | |
generate_n | |
replace | |
replace_if | |
replace_copy | |
replace_copy_if |
3.删除算法
删除一个容器中的某些元素
删除算法不应作用于关联容器(关联容器会涉及到元素排序)
算法复杂度都是o(n)
删除并不会使元素减少
* 将所有应该被删除的元素看做空位子
* 用留下的元素从后往前移, 依次去填空位子
* 空位置填满后,剩下的位置由刚开始的所在位置元素填(即剩下的位置不变)
复制代码
名称 | 说明 |
---|---|
remove | 删除区间中等于某个值的元素 |
unique | 删除区间中连续相等的元素, 只留下一个(可自定义比较器) |
remove_if | |
remove_copy | |
remove_copy_if | |
unique_copy |
4.变序算法
变序算法改变容器中元素的顺序,但是不改变元素的值
变序算法不适用于关联容器
算法复杂度都是O(n)的
名称 | 说明(FwdIt迭代器) |
---|---|
reverse | 颠倒区间的前后次序 |
rotate | 将区间进行循环左移 |
next_permutation | 将区间改为下一个排列(可自定义比较器) |
prev_permutation | 将区间改为上一个排列(可自定义比较器) |
random_shuffle | 随机打乱区间内元素的顺序 |
stable_patition | 把区间内满足某个条件的元素移到前面,不满足该条件的移到后面,而对这两部分元素, 分别保持它们原来的先后次序不变 |
partition | 把区间内满足某个条件的元素移到前面,不满足该条件的移到后面 |
rotate_copy | 将区间以首尾相接的形式进行旋转后的结果拷贝到另一个区间,源区间不变 |
reverse_copy | 把一个区间颠倒后的结果拷贝到另一个区间,源区间不变 |
5.排序算法
排序算法需要随机访问迭代器的支持
不适用于关联容器和list
比前面的变序算法复杂度更高, 一般是O(nlog(n))
名称 | 说明(RanIt迭代器) |
---|---|
sort | void sort(RanIt first, RanIt last, Pred pr) |
stable_sort | |
partial_sort | |
partial_sort_copy | |
nth_element | |
make_heap | |
push_heap | |
pop_heap | |
sort_heap |
sort 实际上是快速排序, 时间复杂度 O(n*log(n))
- 平均性能最优
- 但是最坏的情况下, 性能可能非常差
如果要保证 “最坏情况下” 的性能, 那么可以使用stable_sort
- stable_sort 实际上是归并排序, 特点是能保持相等元素之间的先后次序
- 在有足够存储空间的情况下, 复杂度为 n * log(n), 否则复杂度为n * log(n) * log(n)
- stable_sort 用法和 sort相同。
排序算法要求随机存取迭代器的支持, 所以list不能使用排序算法, 要使用list自带的sort成员函数list::sort。
6.有序区间算法
要求所操作的区间是已经从小到大排好序的
需要随机访问迭代器的支持
有序区间算法不能用于关联容器和list
名称 | 说明(前6个很常用) |
---|---|
binary_search | 判断区间中是否包含某个元素(折半查找) |
includes | 判断是否一个区间中的每个元素,都在另一个区间中 |
lower_bound | 查找最后一个不小于某值的元素的位置 |
upper_bound | 查找第一个大于某值的元素的位置 |
equal_range | 同时获取lower_bound和upper_bound |
merge | 合并两个有序区间到第三个区间 |
set_union | 将两个有序区间的并拷贝到第三个区间 |
set_intersection | 将两个有序区间的交拷贝到第三个区间 |
set_difference | 将两个有序区间的差拷贝到第三个区间 |
set_symmetric_difference | 将两个有序区间的对称差拷贝到第三个区间 |
inplace_merge | 将两个连续的有序区间原地合并为一个有序区间 |
bitset
bitset一个实际上不属于STL算法,但是会很常用。
template<size_t N>
class bitset{
...
}
bitset<40>bst; #bst是一个由40位组成的对象,用bitset的函数可以方便地访问任何一位
复制代码
bitset的成员函数:
bitset<N>& operator&=(const bitset<N>& rhs);
bitset<N>& operator|=(const bitset<N>& rhs);
bitset<N>& operator^=(const bitset<N>& rhs);
bitset<N>& operator<<=(size_t num);
bitset<N>& operator>>=(size_t num);
bitset<N>& set(); //全部设成1
bitset<N>& set(size_t pos, bool val = true); //设置某位
bitset<N>& reset(); //全部设成0
bitset<N>& reset(size_t pos); //某位设成0
bitset<N>& flip(); //全部翻转
bitset<N>& flip(size_t pos); //翻转某位
reference operator[](size_t pos); //返回对某位的引用
bool operator[](size_t pos) const; //判断某位是否为1
reference at(size_t pos);
bool at(size_t pos) const;
unsigned long to_ulong() const; //转换成整数
string to_string() const; //转换成字符串
size_t count() const; //计算1的个数
size_t size() const;
bool operator==(const bitset<N>& rhs) const;
bool operator!=(const bitset<N>& rhs) const;
bool test(size_t pos) const; //测试某位是否为 1
bool any() const; //是否有某位为1
bool none() const; //是否全部为0
bitset<N> operator<<(size_t pos) const;
bitset<N> operator>>(size_t pos) const;
bitset<N> operator~();
static const size_t bitset_size = N;
#注意: 第0位在最右边
复制代码
总结起来呢,就是实现容器或对象元素的查删改比较排序。