目录
下表给出了STL中一些算法的名称、用途、是否质变和文件分布:
算法名称 | 算法用途 | 是否质变 | 所在文件 |
---|---|---|---|
accumulate | 元素累计 | 否 | <numeric> |
adjacent_difference | 计算相邻元素的差值 | 是 | <numeric> |
adjacent_find | 查找相邻而重复的元素 | 否 | <algorithm> |
binarysearch | 二分查找 | 否 | <algorithm> |
copy | 复制 | 是 | <algorithm> |
copy_backward | 逆向复制 | 是 | <algorithm> |
copy_n | 复制 n n n 个元素 | 是 | <algorithm> |
count | 计数 | 否 | <algorithm> |
count_if | 在特定条件下计数 | 否 | <algorithm> |
equal | 判断两个区间是否相等 | 否 | <algorithm> |
equal_range | 在有序区间中寻找某值 | 否 | <algorithm> |
fill | 改填元素值 | 是 | <algorithm> |
fill_n | 改填元素值 n n n 次 | 是 | <algorithm> |
find | 循序查找 | 否 | <algorithm> |
find_if | 循序查找符合特定条件的元素 | 否 | <algorithm> |
find_end | 查找元素最后出现位置 | 否 | <algorithm> |
find_first_of | 查找元素首次出现位置 | 否 | <algorithm> |
for_each | 对区间的每个元素施行操作 | 否 | <algorithm> |
generate | 将特定运算的结果填充到区间内 | 是 | <algorithm> |
generate_n | 将特定运算的结果填充 n n n 个元素 | 是 | <algorithm> |
includes | 检查元素是否包含于序列中 | 否 | <algorithm> |
inner_product | 内积 | 否 | <numeric> |
inplace_merge | 就地归并 | 是 | <algorithm> |
iota | 在区间填入指定值的递增序列 | 是 | <numeric> |
is_heap | 判断某区间是否为堆 | 否 | <algorithm> |
is_sorted | 判断某区间是否已排序 | 否 | <algorithm> |
iter_swap | 迭代器所指元素互换 | 是 | <algorithm> |
lexicographical_cpmpare | 以字典序比较 | 否 | <algorithm> |
lower_bound | “将元素插入序列而不影响 区间原本排序”的最低位置 | 否 | <algorithm> |
max | 最大值 | 否 | <algorithm> |
max_element | 最大值所在位置 | 否 | <algorithm> |
merge | 归并两个序列 | 是 | <algorithm> |
min | 最小值 | 否 | <algorithm> |
min_element | 最小值所在位置 | 否 | <algorithm> |
mismatch | 失配位置 | 否 | <algorithm> |
next_permutation | 下一个排列组合 | 是 | <algorithm> |
nth_element | 区间第 n n n 小 | 否 | <algorithm> |
partial_sort | 局部排序 | 是 | <algorithm> |
partial_sort_copy | 局部排序并复制到他处 | 是 | <algorithm> |
partial_sum | 局部求和 | 是 | <numeric> |
partition | 分割 | 是 | <algorithm> |
prev_permutation | 前一个排列组合 | 是 | <algorithm> |
power | 求幂次 | 否 | <numeric> |
random_shuffle | 随机重排元素 | 是 | <algorithm> |
random_sample | 随机取样 | 是 | <algorithm> |
random_sample_n | 随机 n n n 次取样 | 是 | <algorithm> |
remove | 删除某类元素 | 是 | <algorithm> |
remove_copy | 删除某类元素并将结 果复制到另一个容器 | 是 | <algorithm> |
remove_if | 有条件地删除某类元素 | 是 | <algorithm> |
remove_copy_if | 有条件地删除某类元素并 将结果复制到另一个容器 | 是 | <algorithm> |
replace | 替换某类元素 | 是 | <algorithm> |
replace_copy | 替换某类元素并将结 果复制到另一个容器 | 是 | <algorithm> |
replace_if | 有条件地替换 | 是 | <algorithm> |
replace_copy_if | 有条件地替换并将结 果复制到另一个容器 | 是 | <algorithm> |
reverse | 反转元素次序 | 是 | <algorithm> |
reverse_copy | 反转元素次序并将结 果复制到另一个容器 | 是 | <algorithm> |
rotate | 旋转 | 是 | <algorithm> |
rotate_copy | 旋转并将结果复 制到另一个容器 | 是 | <algorithm> |
search | 查找某个子序列 | 否 | <algorithm> |
search_n | 查找连续发生 n n n 次的子序列 | 否 | <algorithm> |
set_difference | 差集 | 是 | <algorithm> |
set_intersection | 交集 | 是 | <algorithm> |
set_symmetric_difference | 对称差 | 是 | <algorithm> |
set_union | 并集 | 是 | <algorithm> |
sort | 排序 | 是 | <algorithm> |
stable_partition | 稳定型分割 | 是 | <algorithm> |
stable_sort | 稳定型排序 | 是 | <algorithm> |
swap | 交换元素 | 是 | <algorithm> |
swap_ranges | 交换指定区间 | 是 | <algorithm> |
transform | 以两个序列为基础,交 互作用产生第三个序列 | 是 | <algorithm> |
unique | 去重 | 是 | <algorithm> |
unique_copy | 去重并将结果复制到他处 | 是 | <algorithm> |
upper_bound | “将元素插入序列而不影响 区间原本排序”的最高位置 | 否 | <algorithm> |
make_heap | 制造堆 | 是 | <algorithm> |
pop_heap | 从堆中取出一个元素 | 是 | <algorithm> |
push_heap | 将元素放进堆中 | 是 | <algorithm> |
sort_heap | 对堆进行排序 | 是 | <algorithm> |
下面逐个介绍一些这些算法的用法。
STL算法的一般形式
所有泛型算法的前两个参数都是一对迭代器,通常称为 first \text{first} first 和 last \text{last} last ,用以标示算法的操作区间。STL习惯采用前闭后开区间表示法,写成 [ first , last ) [\text{first},\text{last}) [first,last) 。这个区间必须满足的条件为,必须能经由累加(increment)操作符的反复运用,否则会导致无法预期的错误,且这个错误不一定在编译的时候被捕捉。
根据行进特性,迭代器分五种:Input Iterator、Output Iterator、Forward Iterator、Bidirectional Iterator、Random Access Iterator。这五种迭代器的逻辑层次见下图。每一个STL算法的声明都表现出它所需要的最低程度的迭代器类型。比如 find()
函数,它需要一个Input Iterator,但你给它传Forward Iterator或Bidirectional Iterator等都可以,就是不能传Output Iterator,否则会导致错误。同样,将无效的迭代器传给某个算法并不能保证在编译的时候能被捕捉,因此一定要小心使用。
许多STL算法不止支持一个版本。这一类的算法的某个版本采用缺省运算行为,另一个版本提供额外参数,接受外界传入一个仿函数,以便采用其他策略,这种函数一般会用"_if"结尾表示。
质变算法通常提供两个版本,就地的和复制到他处的,一般复制到他处的会以"_copy"结尾表示。当然并非所有质变算法都有copy版本,如 sort()
就没有。
所有的数值算法都实现于 <stl_numeric.h>
中,但这是内部文件,规定用户必须包含其上层的 <numeric>
。其他的算法实现于 <stl_algo.h>
和 <stl_algobase.h>
中,也都是内部文件,欲使用这些算法须包含上层头文件 <algorithm>
。
数值算法
这一部分的算法都包含在 <numeric>
头文件中。
accumulate
该算法用来计算区间
[
first
,
last
)
[\text{first},\text{last})
[first,last) 内的元素和,使用时需要提供初始值 init
,算法返回和的值。
//版本一
template <class InputIterator, class T>
T accumulate(InputIterator first, InputIterator last, T init);
//版本二
template <class InputIterator, class T, class BinaryOperation>
T accumulate(InputIterator first, InputIterator last, T init,
BinaryOperation binary_op);
adjacent_difference
该算法用来计算区间
[
first
,
last
)
[\text{first},\text{last})
[first,last) 中相邻元素的差值,需要传进一个 result
迭代器,算法将 *first
赋给 *result
,并针对
[
first
+
1
,
last
)
[\text{first}+1,\text{last})
[first+1,last) 内的每个迭代器 i
,将 *i - *(i-1)
赋给 *(result + (i - first))
,算法返回区间的尾端位置。
//版本一
template <class InputIterator, class OutputIterator>
OutputIterator adjacent_difference(InputIterator first, InputIterator last,
OutputIterator result);
//版本二
template <class InputIterator, class OutputIterator, class BinaryOperation>
OutputIterator adjacent_difference(InputIterator first, InputIterator last,
OutputIterator result,
BinaryOperation binary_op);
inner_product
该算法可以计算
[
first1
,
last1
)
[\text{first1},\text{last1})
[first1,last1) 和
[
first2
,
last2
)
[\text{first2},\text{last2})
[first2,last2) 的内积,需要提供初始值 init
,算法返回内积的值。
//版本一
template <class InputIterator1, class InputIterator2, class T>
T inner_product(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, T init);
//版本二
template <class InputIterator1, class InputIterator2, class T,
class BinaryOperation1, class BinaryOperation2>
T inner_product(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, T init,
BinaryOperation1 binary_op1,//加法
BinaryOperation1 binary_op2);//乘法
partial_sum
该算法用来计算局部总和。它会将 *first
赋给 *result
,将 *first
和 *(first + 1)
赋给 *(result + 1)
,依此类推,算法返回区间的尾端位置。
//版本一
template <class InputIterator, class OutputIterator>
OutputIterator partial_sum(InputIterator first, InputIterator last,
OutputIterator result);
//版本二
template <class InputIterator, class OutputIterator, class BinaryOperation>
OutputIterator partial_sum(InputIterator first, InputIterator last,
OutputIterator result, BinaryOperation binary_op);
power
这个算法由SGI专属,不在STL标准之列。它用来计算某个数的 n n n 幂次方,运算类型可由外界指定,但运算必须满足结合律(Monoid意味独异点)。算法返回幂次的值。
//版本一
template <class T, class Integer>
inline T power(T x, Integer n);
//版本二
template <class T, class Integer, class MonoidOperation>
T power(T x, Integer n, MonoidOperation op);
iota
这个算法由SGI专属,不在STL标准之列。它用来设定某个区间的内容,使其内的每一个元素从指定的 value
值开始,呈现递增状态,即,在区间
[
first
,
last
)
[\text{first},\text{last})
[first,last) 内填入 value
, value + 1
, value + 2
,……。该算法无返回值。
template <class ForwardIterator, class T>
void iota(ForwardIterator first, ForwardIterator last, T value);
基本算法
在SGI中,一些常用的算法位于 <stl_algobase.h>
中,其他算法定义于 <syl_algo.h>
中,以下是定义在 <stl_algobase.h>
中的算法。
equal
如果两个序列在
[
first
,
last
)
[\text{first},\text{last})
[first,last) 区间内相等,函数返回 true
。如果第二序列的元素比较多,多出来的元素不考虑。如果第二序列的元素比第一序列少,算法的内部迭代会超过序列的尾端,造成不可预测的结果。
//版本一
template <class InputIterator1, class InputIterator2>
inline bool equal(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2);
//版本二
template <class InputIterator1, class InputIterator2,
class BinaryPredicate>
inline bool equal(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, BinaryPredicate binary_pred);
fill
该算法将
[
first
,
last
)
[\text{first},\text{last})
[first,last) 内的所有元素改填新值。值得注意的是,该算法就是一个线性遍历赋值,所以能用 memset
就尽量不用 fill
。
template <class ForwardIterator, class T>
void fill(ForwardIterator first, ForwardIterator last, const T& value);
fill_n
该算法将 [ first , last ) [\text{first},\text{last}) [first,last) 内的前 n n n 个元素改填新值,返回被改填新值区间的尾端位置。须注意,若 n n n 超过了区间的长度将产生不可预期的结果。
template <class OutputIterator, class Size, class T>
OutputIterator fill_n(OutputIterator first, Size n, const T& value);
iter_swap
该算法将两个 Forward Iterator 所指的对象对调,两迭代器所指对象类型可以不同,用的是三变量交换法(这里就能看出traits技法的妙处了)。
template <class ForwardIterator1, class ForwardIterator2>
inline iter_swap(ForwardIterator1 a, ForwardIterator2 b);
lexicographical_compare
该算法以“字典排序方式”对两个序列 [ first1 , last1 ) [\text{first1},\text{last1}) [first1,last1) 和 [ first2 , last2 ) [\text{first2},\text{last2}) [first2,last2) 进行比较。即,长度不同则短的比长的小,长度相同则第一个不同元素小的那个小。
//版本一
template <class InputIterator1, class InputIterator2>
bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2);
//版本二
template <class InputIterator1, class InputIterator2, class Compare>
bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
Compare comp);
此外,为了增进效率,SGI还设计了用于原生指针 const unsigned char*
和 const char*
的特化版本,里面用到了 memcmp
函数。
max
取两个对象中的最大值。要求两个对象的类型必须一样。
//版本一
template <class T>
inline const T& max(const T& a, const T& b);
//版本二
template <class T, class Compare>
inline const T& max(const T& a, const T& b, Compare comp);
min
取两个对象中的最小值。要求两个对象的类型必须一样。
//版本一
template <class T>
inline const T& min(const T& a, const T& b);
//版本二
template <class T, class Compare>
inline const T& min(const T& a, const T& b, Compare comp);
mismatch
用来平行比较两个序列,指出两者之间的第一个不匹配点。返回一对迭代器,分别指向两序列中的不匹配点。算法要求第二序列的元素个数大于等于第一序列的。
//版本一
template <class InputIterator1, class InputIterator2>
pair<InputIterator1, InputIterator2> mismatch(InputIterator1 first,
InputIterator1 last1,
InputIterator2 first2);
//版本二
template <class InputIterator1, class InputIterator2,
class BinaryPredicate>
pair<InputIterator1, InputIterator2> mismatch(InputIterator1 first,
InputIterator1 last1,
InputIterator2 first2,
BinaryPredicate binary_pred);
swap
该函数用来交换两个相同类型对象的内容,依然是三变量交换法。
template <class T>
inline void swap(T& a, T& b);
copy
该算法将输入区间
[
first
,
last
)
[\text{first},\text{last})
[first,last) 内的元素复制到输出区间
[
result
,
result
+
(
last
−
first
)
)
[\text{result},\text{result} + (\text{last} - \text{first}))
[result,result+(last−first)) 内。算法并不是简单的遍历,它除了可以避免输入输出区间重叠而可能产生的错误(首先用了 memmove
把整个输入区间内容复制下来),也尽量进行了一些优化。
template <class InputIterator, class OutputIterator>
inline OutputIterator copy(InputIterator first, InputIterator last,
OutputIterator result);
copy_backward
与 copy
完成的事情相同,不过复制的顺序是相反的。即, copy
执行赋值操作 *result = *first
, *(result + 1) = *(first + 1)
,……,而 copy_backward
执行 *(result - 1) = *(last - 1)
, *(result - 2) = *(last - 2)
,……。
template <class BidirectionalIterator1, class BidirectionalIterator2>
inline BidirectionalIterator2 copy_backward(BidirectionalIterator1 first,
BidirectionalIterator1 last,
BidirectionalIterator2 result);
算了,算法太多写不完了,剩下的就对着表格看,然后百度查吧……