《Thinking in C++> STL算法总结笔记。
STL算法目录
文章目录
0.算法总览
fill()
,为[first, last)每个元素赋值value。fill_n()
,由first开始的n个元素赋值value。generate()
,用发生器为[first, last)的每个元素生成一个值。generate_n()
为first开始的n个元素生成一个值。count()
,范围内等于value的个数。count_if()
,范围内是判定函数为真的个数。copy()
,从[first, last)复制序列到destination。copy_backward()
,反向复制元素。reverse()
,倒置源序列reverse_copy()
,源序列不变,导致结果复制到destination。swap_ranges()
,交换相等大小两个范围的内容rotate()
,把[first, middle)范围元素移到序列末尾,[middle, last)移到序列开始。rotate_copy()
,不改变原始序列,轮换结果复制到destination。next_permutation()
,后继排列prev_permutation()
,前驱排列random_shuffle()
,重新排列元素(混洗)partition()
,将满足判定函数的元素移动到序列开头。stable_partition()
,稳定划分,保持相对位置不变find()
,查找value第一次出现的位置find_if()
,查找使判定函数为真的元素。adjacent_find()
查找两个邻近的相等元素。find_first_of()
,在第二个范围内查找与第一个范围内的某个元素相等的元素。search()
,查找第二个序列第一次出现在第一个序列的位置。find_end()
,查找第二个序列最后一次出现在第一个序列的位置。search_n()
,在范围内查找一组共count个连续的值。min_element()
,最小值首次出现的位置。max_element()
,最大值首次出现的位置。replace()
,旧值替换为新值。replace_if()
,使判定函数为真的值替换为新值。replace_copy()
,不修改原始序列,替换旧值放入result。replace_copy_if()
,不修改原始序列,替换使判定函数为真的值放入result。equal()
,判断两个范围内元素是否完全相同。lexicographical_compare()
,第一个范围是否“字典序小于”第二个范围。mismatch()
,两个范围不匹配的位置。remove()
,删除等于value的元素。remove_if()
,删除使判定函数为真的元素。remove_copy()
,不改变源序列。remove_copy_if()
,不改变源序列。unique()
,删除相邻的相等值(副本)。unique_copy()
,不改变源序列。sort()
,升序排序。stable_sort()
,稳定升序排序。partital_sort()
,对一定元素进行排序,使其有序放入[first, middle)中。partital_sort_copy()
,不改变源序列。nth_element()
,使[first, nth]内所有元素都满足二元判定函数。binary_search()
,告诉value是否出现在有序序列中。lower_bound()
,value第一次出现的位置。upper_bound()
,超越value最后出现的位置。equal_range()
,value第一次和超越最后一次出现的位置。merge()
,升序合并序列。inplace_merge()
,升序合并同一序列的两个范围。includes()
,判断第二个范围是否是第一个范围子集。set_union()
,并集。set_intersection()
,交集。set_difference()
,差。set_symmetric_difference()
,对称差。make_heap()
,建堆。push_heap()
,向[first, last-1)堆中增加元素*(last-1)并放入合适位置。pop_heap()
,将最大元素*first放入位置(last-1)并调整堆。sort_heap()
,堆排序,使堆转为有序序列,不稳定排序。for_each()
,遍历运算,丢弃调用返回值。transform()
,遍历运算,保留调用返回值。accumulate()
,合计。inner_product()
,广义内积。partial_sum()
,广义部分和。adjacent_difference()
,相邻元素差。make_pair()
,两个对象封装为一个对象。distance()
,[first, last)之间的元素个数。back_inserter()
,迭代器。front_inserter()
,迭代器。inserter(),迭代器。
min()
,较小值。max()
,较大值。swap()
,交换a和b。
1.迭代器形式:
- InputIterator。一个只允许单个向序列输入迭代器,前向传递使用operator++和operator*。可以通过operator==和operator!=检测输入迭代器,这是约束的范围。
- OutputIterator。一个只允许单个向序列写入的元素的输出迭代器,前向传递使用operator++和operator*。可以持有无限个对象,不需要结尾检查,可以和ostream(通过ostream_iterator)一起使用,也普遍使用插入迭代器(back_insert()返回的迭代器类型。
- ForwardIterator。仍然仅用operator++前向移动,但是可以同时进行读和写和判断相等。
- BidirectionalIterator。支持ForwardIterator的全部操作,还增加了operator--运算,支持后向移动。
- RandomAccessIterator。支持一个常规指针所做的全部运算:可以通过增加和减少某个整数值,来向前和向后跳跃移动(不是每次只移动一个元素),还可以用operator[]作为下标索引,可以从一个迭代器中减去另一个迭代器,也可以用operator<,operator>来比较迭代器大小。
2.填充和生成
这些算法能够自动用一个特定值来填充(容器中的)某个范围的数据,或为(容器中的)某个特定范围生成一组值。
-
填充(fill):向容器多次插入一个值。
void fill(ForwardIterator first, ForwardIterator last, const T& value); void fill_n(OutputIterator first, Size n, const T& value);
-
fill()
对[fitst, last)的每个元素赋值value。 -
fill_n()
对由first开始的n个元素赋值value。
-
-
生成(generate):使用发生器来产生插入到容器的值。
void generate(ForwardItertor first, ForwardIterator last, Generator gen); void generate_n(OutputIterator first, Size n, Generator gen);
-
generate()
为[fitst, last)的每个元素进行一个gen()
调用,可以假设为每个元素产生一个不同的值。 -
generate_n()
对gen()
调用n次,并赋值给由first开头的n个元素。
-
3. 计数
所有容器都含有一个成员函数size()
,它可以告诉该容器包含多少个元素。size()
的返回类型是迭代器的difference_type(通常是ptrdiff_t)。
-
计数(count):对满足一定标准的对象计数
IntegraValue count(InputIterator first, InputIterator last, const EqualityComparable& value);
count()
这个算法产生[first, last)范围内等于value的元素个数(相当于operator==)
IntegraValue count_if(InputIterator first, InputIterator last, Predicate pred);
count_if()
这个算法产生[first, last)范围内能使pred返回true的元素个数。
4. 操作序列
-
移动序列(copy):
OutputIterator copy(InputIterator first, InputIterator last, OutputIteratot destination);
copy()
使用赋值,从范围[first, last)复制序列到destination,每次赋值后都增加destination。本质是“左混洗(shuffle-left)”运算,所以源序列不能包含目的序列。由于使用赋值操作,因此不能直接向空容器或容器尾插入元素,必须把destination迭代器封装在insert_iterator里(典型的使用back_inserter()
或inserter()
)。
BidirectionalIterator2 copy_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 destinationEnd);
copy_backward()
同copy一样,但是以相反的顺序复制元素。本质是“右混洗(shuffle-right)”运算。第一个目标元素是destinationEnd-1。目的序列范围的空间必须已经存在(允许赋值)。
-
翻转(reverse):
void reverse(BidirectionalIterator first, BidirectionalIterator last); OutputIterator reverse_copy(BidirectionalIterator first, BidirectionalIterator last, OutputIterator destination);
reverse()
倒置源序列范围的元素reverse_copy()
保持源序列范围元素顺序不变,将倒置的元素复制到destination,返回结果序列范围的超越末尾(past-the-end)的迭代器。
-
交换(swap):
ForwardIterator2 swap_ranges(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2);
swap_ranges()
通过交换对应的元素来交换相等大小两个范围的内容。
-
轮换(rotate):
void rotate(ForwardIterator first, ForwardIterator middle, ForwardIterator last); OutputIterator rotate_copy(ForwardIterator first, ForwardIterator middle, ForwardIterator last, OutputIterator destination);
rotate()
把[first, middle)范围中的内容移到该序列的末尾,并且将[middle, last)范围中的内容移动到该序列的开始位置,使用rotate()再适当的位置执行变化。rotate_copy()
不改变原始序列范围,且将轮换后的元素复制到destination中,返回结果超越末尾的迭代器。
-
排列(permutation):
排列是一组元素的一种独一无二的排序,如果有n个元素,则有n!中不同的元素组合。这些组合概念化地以词典编纂(类似字典)的顺序排序,就产生了前驱(previous)和后继(next)排列的概念。
bool next_permutation(BidirectionalIterator first, BidirectionalIterator last); bool next_permutation(BidirectionalIterator first, BidirectionalIterator last, StrictWeakOrdering binary_pred); bool prev_permutation(BidirectionalIterator first, BidirectionalIterator last); bool prev_permutation(BidirectionalIterator first, BidirectionalIterator last, StrictWeakOrdering binary_pred);
next_permutation()
和prev_permutation()
函数对元素重新排列成后记或前驱排列,如果成功则返回true。如果没有多个“后继”排序,元素以升序排列,next_permutation()返回false。如果没有多个前驱序列,元素以降序排列,prev_permutation()返回false。- 具有StrictWeakOrdering参数的函数形式用binary_pred来执行比较,而不是operator<。
-
混洗(shuffle):
void random_shuffle(RandomAccessIterator first, RandomAccessIterator last); void random_shuffle(RandomAccessIterator first, RandomAccessIterator last, RandomNumberGenerator& rand);
random_shuffle
这个函数随机地重排范围内地元素。如果用随机数发生器,则产生均匀的分布结果。第一种形式使用内部随机数发生器,第二种使用用户提供的随机数发生器。对于正数n发生器必须返回一个[0, n)范围内的值。
-
划分(partition):
BidirectionalIterator partition(BidirectionalIterator first, BidirectionalIterator last, Predicate pred); BidirectionalIterator stable_partition(BidirectionalIterator first, BidirectionalIterator last, Predicate pred);
- 这些函数将满足pred的元素移动到序列的开始位置。迭代器指向其返回元素位置,该元素是超越这些元素中的最后一个(以满足pred的子序列)。这个位置称为“划分点(partition point)”
partition()
没有指定子序列元素的顺序,stable_partition()
划分之后元素的相对位置不变。
5. 查找和替换
这些算法用来在某个范围内查找一个或多个对象,该范围由两个迭代器参数定义。
-
查找(find):
InputIterator find(InputIterator first, InputIterator last, const EqualityComparable& value);
find()
算法在[first, last)内查找value第一次出现的位置,如果value不在范围内,则返回last。这是线性查找(linear search),不对元素的顺序路径做任何假设。binary_search()
是在有序的序列上工作,能更快的查找。
InputIterator find_if(InputIterator first, InputIterator last, Predicate pred);
find_if()
在指定范围内执行线性查找,寻找一个满足pred的元素(使Predicate pred返回true),找不到则返回last。
ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last); ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last, BinaryPredicate binary_pred);
adjacent_find()
进行线性查找,查找两个邻近的相等元素。第一种形式查找两个相等的元素(通过operator==)。第二种形式查找两个邻近的元素,当找到这两个元素并一起传递给binary_pred时产生true。如果找到这样的一对则返回指向第一个元素的迭代器,否则返回last。
ForwardIterator1 find_first_of(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); ForwardIterator1 find_first_of(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator last2, BinaryPredicate binary_pred);
find_first_of()
在指定范围内执行线性查找,在第二个范围内查找与第一个范围内的某个元素相等的元素。第一种形式使用operator==, 第二种形式使用判定函数。
ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate binary_pred);
search()
算法检查第二个序列范围是否出现在第一个序列的范围内(顺序完全一致),如果是则返回一个迭代器,指向第一个范围序列中第二个序列出现的开始位置。没有找到则返回last1。第一种形式使用operator==, 第二种形式检测每对元素是否能使binary_pred返回true。
ForwardIterator1 find_end(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); ForwardIterator1 find_end(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate binary_pred);
find_end()
与search()类似,查找第二个范围的序列是否使第一个范围序列的子集,search()
查找该子集首次出现的位置,find_end()
查找最后出现的位置。返回指向该子集的第一个元素的迭代器。
ForwardIterator search_n(ForwardIterator first, ForwardIterator last, Size count, const T& value); ForwardIterator search_n(ForwardIterator first, ForwardIterator last, Size count, const T& value, BinaryPredicate binary_pred);
search_n()
在[first, last)内查找一组共count个连续的值,这些值都与value相等(第一种形式),或是将所有这些与value相同的值传递给binary_pred时返回true(第二种形式)。找不到则返回last。
ForwardIterator min_element(ForwardIterator first, ForwardIterator last); ForwardIterator min_element(ForwardIterator first, ForwardIterator last, BinaryPredicate binary_pred);
min_element()
返回一个迭代器,指向范围内“最小值”首次出现的地方。如果范围为空则返回last。第一种形式用operator<执行比较,且返回值为r(对范围[first, r)中的每个元素e,*e<*r都为假)。第二种形式用binary_pred比较,返回值是r(对于范围[first, r)中的每个元素e, binary_pred(*e, *r)都为假。
ForwardIterator max_element(ForwardIterator first, ForwardIterator last); ForwardIterator max_element(ForwardIterator first, ForwardIterator last, BinaryPredicate binary_pred);
max_element()
指向范围内最大值首次出现的地方。第一种形式用operator<执行比较,且返回值为r(对范围[first, r)中的每个元素e,*r<*e都为假)。第二种形式用binary_pred比较,返回值是r(对于范围[first, r)中的每个元素e, binary_pred(*r, *e)都为假。
-
替换(replace):
void replace(ForwardIterator first, Forwarditerator last, const T& old_value, const T& new_value); void replace_if(ForwardIterator first, Forwarditerator last, Predicate pred, const T& new_value); OutputIterator replace_copy(InputIterator first, InputIterator last, OutputIterator result, const T& old_value, const T& new_value); OutputIterator replace_copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred, const T& new_value);
reaplace()
和replace_copy()
在[first, last)内查找old_value并替换为new_value。replace_if()
和replace_copy_if()
查找满足判定函数pred的值并替换。- copy形式的函数不修改原始范围,而将作为替换的副本赋值给result,每次赋值后增加result。
6. 比较范围
以下算法提供比较两个范围的方法。
-
比较:
bool equal(InputIterator first1, InputIterator last1, InputIterator first2); bool equal(InputIterator first1, InputIterator last1, InputIterator first2, BinaryPredicate binary_pred);
equal()
算法中,第二个范围始于first2,长度取决于第一个范围。如果两个范围完全相同(有相同元素和顺序),则返回true。第一种形式使用operator==,第二种形式由binary_pred来决定两个元素是否相同。
bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2); bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, BinartPredicate binary_pred);
lexicographical_compare()
决定第一个范围是否“字典序小于(lexicographically less)”第二个范围。如果小于则返回true。如果完全相等,范围1不小于范围2,则返回false。- 如果两个范围长度不同,按字典序,一个范围内缺少的元素起到“领先于(precede)”另一个范围的元素的作用,因此“abc”领先于“abcd”。如果算法执行到结尾任没有不匹配的元素对,此时短范围领先,如果第一个范围是短范围,则返回true。
- 大写字母领先于小写字母。
- 第一种形式由operator<执行比较,第二种形式使用binary_pred。
pair<InputIterator1, InputIterator2> mismatch(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2); pair<InputIterator1, InputIterator2> mismatch(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryPredicate binary_pred);
-
mismatch()
指出两个范围从哪里开始不同。为了完成这一工作,必须知道:- 第一个范围内出现不匹配元素的位置
- 第二个范围内出现不匹配元素的位置。
将这两个迭代器一起装入一个pair对象并返回。如果没有不匹配,返回值是与第二个范围结合在一起的超越末尾的迭代器last1。pair模板类含有成员名first 和 second表示的元素,定义在<utility>中。
7. 删除元素:
STL“删除”函数重新排列该序列,将“已被删除的”元素排在序列的末尾,“未删除的”排在序列的开头,返回一个指向序列的“新末尾”元素的迭代器(不包含删除元素的序列的末尾)。
如果new_last是删除函数返回的迭代器,则范围[first, new_last)是不包含任何被删除元素的序列,而范围[new_last, last)是被删除元素组成的序列。
-
删除(remove):
ForwardIterator remove(ForwardIterator first, ForwardIterator last, const T& value); ForwardIterator remove_if(ForwardIterator first, ForwardIterator last, Predicate pred); OutputIterator remove_copy(InputIterator first, InputIterator last, OutputIterator result, const T& value); OutputIterator remove_copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred);
- 这里的每一种“删除”都从头到尾遍历[first, last),找到符合删除标准的值,并且复制未被删除的元素覆盖已被删除的元素。未被删除的元素保持原始排序。返回超越末尾的迭代器,该范围不包含任何已被删除的元素,迭代器指向的元素的值未被指定。
- if版本的删除把每一个元素传递给判定函数pred()来决定是否删除(如果pred()返回true则删除)。
- copy版本不改变原始序列,复制未被删除的值到一个始于result的新范围并返回指向新范围的超越末尾迭代器。
-
去重(unique):
ForwardIterator unique(ForwardIterator first, ForwardIterator last); ForwardIterator unique(ForwardIterator first, ForwardIterator last, BinaryPredicate binary_pred); OutputIterator unique_copy(InputIterator first, InputIterator last, OutputIterator result); OutputIterator unique_copy(InputIterator first, InputIterator last, OutputIterator result, BinaryPredicate binary_pred);
-
这里的每一种
unique()
算法遍历[first, last),找到相邻的相等值(副本),通过复制覆盖它们来删除副本。未被删除的元素原始顺序不变。返回超越末尾的迭代器,该范围相邻副本已被删除。 -
由于只删除相邻的副本,因此在
unique()
之前调用sort()
,确保全部副本都被删除。 -
对于包含binary_pred调用版本中:
binary_pred(*i, *(i-1));
如果返回true,则认为*i是一个副本。
-
copy版本不改变原始序列,将未被删除的值放到开始于result的新范围,并返回超越新范围末尾的迭代器。
-
8. 对已排序的序列进行排序和运算
STL提供了大量独立的排序算法,分别对应于稳定的、部分的或仅是规则的(不稳定)排序。只有部分排序有复制的版本。
对已排好序的序列进行包括排序或运算的每个算法都有两种版本。第一种使用对象自己的operator<来执行比较,第二种使用operator()(a, b)来决定a和b的相对顺序。
-
排序(sort):
排序算法需要由随机存取的迭代器来限制序列的范围,如vector或deque。list容器有自己的嵌入sort()杉树,因为它仅提供双向的迭代。
void sort(RandomAccessIterator first, RandomAccessIterator last); void sort(RandomAccessIterator first, RandomAccessIterator last, StrictWeakOrdering binary_pred);
sort()
将[first, last)范围内的序列按升序排序。第一种使用operator<,第二种使用提供的比较器对象来决定顺序。
void stable_sort(RandomAccessIterator first, RandomAccessIterator last); void stable_sort(RandomAccessIterator first, RandomAccessIterator last, StrictWeakOrdering binary_pred);
stable_sort()
进行稳定的升序排序,保持相等元素的原始顺序。
void partital_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last); void partital_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, StrictWeakOrdering binary_pred)
partital_sort()
对[first, last)范围中一定数量元素进行排序,这些元素可以放入范围[first, middle)中。排序结束时,在范围[middle, last)中其余的元素不保证他们的顺序。
RandomAccessIterator partial_sort_copy(InputIterator first, InputIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last); RandomAccessIterator partial_sort_copy(InputIterator first, InputIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last, StrictWeakOrdering binary_pred);
partital_sort_copy()
对[first, last)中的一定数量的元素排序,这些元素可以放入[result_first, result_last)中,并且复制到其中。如果[first, last)比[result_first, result_last)小,则使用较少的元素。
void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last); void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last, StrictWeakOrdering binary_pred);
nth_element()
如同partital_sort,部分的处理(排列)范围内的元素。但比partital_sort少处理得多。nth_element
唯一保证无论选择什么位置,该位置都会成为一个分界点。范围[first, nth]内的所有元素都会成对的满足二元判定函数(通常默认是operator<),而范围(nth, last]内的所有元素都不满足该判定。- 任意一个范围都没有排序,而partital_sort()的第一个范围已排好序。
- 如果需要很弱的排序处理(如中值、百分点等),这个算法比
partital_sort()
快得多。
-
有序序列查找:
如果在未排序的范围内使用这些函数,结果不可预料。
bool binary_search(ForwardIterator first, ForwardIterator last, const T& value); bool binary_search(ForwardIterator first, ForwardIterator last, const T& value, StricWeakOrdering binary_pred);
binary_search()
告诉value是否出现在已排序的范围[first, last)中。- 二分查找使用的是前向顺序查找的迭代器而不是随机存取迭代器,是因为随机存取迭代器“是(is-a)”向前顺序查找迭代器。如果传递给这些算法之一的迭代器实际支持随机存取,则使用对数时间查找,否则执行线性查找。
ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value); ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value, StricWeakOrdering binary_pred);
lower_bound()
返回一个迭代器,指出value在已排序的范围[first, last)中第一次出现的位置。如果value没有出现,返回的迭代器则指出它应该在序列中出现的位置。
ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value); ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value, StricWeakOrdering binary_pred);
upper_bound()
返回一个迭代器,指出value在已排序的范围[first, last)中超越value最后出现的一个位置。如果value没有出现,返回的迭代器则指出它应该在序列中出现的位置。
pair<ForwardIterator, ForwardIterator> equal_range(ForwardIterator first, ForwardIterator last, const T& value); pair<ForwardIterator, ForwardIterator> equal_range(ForwardIterator first, ForwardIterator last, const T& value, StrictWeakOrdering binary_pred);
equal_range()
本质上结合了lower_bound()和upper_bound(),返回一个指出value在已排序范围[first, last)中首次和超越最后出现的pair。如果没有找到,则两个迭代器指出value在该序列中应该出现的位置。
-
合并有序序列(merge):
OutputIterator merge(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); OutputIterator merge(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, StrictWeakOrdering binary_pred);
merge()
从[first1, last1)和[first2, last2)中复制元素到result中,在结果范围的序列以升序排序,是稳定的运算。
void inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last); void inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, StrictWeakOrdering binary_pred);
inplace_merge()
假定[first, middle)和[middle, last)是在相同的序列中已排好序的两个范围,合并这两个范围到一个结果序列[first, last),结合成一个有序的序列。
-
集合运算:
一旦范围排好序,就可以执行数学集合运算。
bool includes(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2); bool includes(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, StrictWeakOrdering binary_pred);
includes()
算法中,如果[first2, last2)是[first1, last1)的一个子集,返回true。没有任何一个范围要求只持有与另一个范围完全不同的元素,但如果[first2, last2)持有n个特定的元素,假如要返回true,则[first1, last1)也必须同时持有至少n个元素。
OutputIterator set_union(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); OutputIterator set_union(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, StrictWeakOrdering binary_pred);
set_union()
算法在result范围中创建两个已排序范围的数学并集,返回值指向输出范围的末尾。没有任何一个输入范围要求只持有与另一个范围完全不同的元素,但是,如果在两个输入集合中多次出现某个特定值,结果集合中将包含完全相同的值出现的较大次数。
OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, StrictWeakOrdering binary_pred);
set_intersection()
算法在result中产生两个输入集合的交集,返回值指向输出范围的末尾。如果某个特定值在两个输入集合中多次出现,结果集合中将包含完全相同的值出现的较小次数。
OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, StrictWeakOrdering binary_pred);
set_difference()
算法产生数学上集合的差,返回值指向输出结果范围的末尾。所有出现在[first1, last1)中,但不在[first2, last2)中出现的所有元素放入结果集合。如果某个特定值在两个输入集合中多次出现(在集合1中n次,集合2中m次),结果集合将包含这个值的max(n-m,0)个副本。
OutputIterator set_symmetric_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); OutputIterator set_symmetric_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, StrictWeakOrdering binary_pred);
-
set_symmetric_difference()
算法的result集合构成中,包括:- 所有在集合1而不在集合2中的元素。
- 所有在集合2而不在集合1中的元素。
如果某个特定值在两个输入集合中多次出现(在集合1中n次,集合2中m次),结果集合将包含这个值的abs(n-m)个副本,其中abs()是取绝对值函数。返回值指向输出结果范围的末尾。
9. 堆运算
标准库中的堆运算允许一个序列被视为是一个”堆“数据结构,可以高效的返回最高优先权的元素,而无需全部排序整个序列。
优先权是依据某些比较函数决定的。第一种版本通过operator<执行比较,第二种版本使用StrictWeakOrdering对象的operator()(a, b)来比较两个对象:a<b。
-
堆(heap):
void make_heap(RandomAccessIterator first, RandomAccessIterator last); void make_heap(RandomAccessIterator first, RandomAccessIterator last, StrictWeakOrdering binary_pred);
make_heap()
算法将一个任意序列范围转化成堆。
void push_heap(RandomAccessIterator first, RandomAccessIterator last); void push_heap(RandomAccessIterator first, RandomAccessIterator last, StrictWeakOrdering binary_pred);
push_heap()
算法向由范围[first, last-1)决定的堆中增加元素*(last-1)。将最后一个元素放入堆中适合的位置。
void pop_heap(RandomAccessIterator first, RandomAccessIterator last); void pop_heap(RandomAccessIterator first, RandomAccessIterator last, StrictWeakOrdering binary_pred);
pop_heap()
算法将最大的元素*first 放入位置*(last-1)并重新组织剩余的范围,使其保持堆的结构。如果只取*first,下一个元素将不是下一个最大的元素,故要保持堆,必须调用pop_heap()完成运算。
void sort_heap(RandomAccessIterator first, RandomAccessIterator last); void sort_heap(RandomAccessIterator first, RandomAccessIterator last, StrictWeakOrdering binary_pred);
sort_heap()
算法使一个以堆顺序排列的序列,转化成普通的排列顺序,这样它就不再是一个堆。不稳定排序。- 调用sort_heap()后将不能在这个序列范围内调用push_heap()或pop_heap()。
10. 对某一范围内的所有元素进行运算
这些算法遍历整个范围并对每个元素执行运算。
-
遍历运算:
UnaryFunction for_each(InputIterator first, InputIterator last, UnaryFuction f);
for_each()
算法对[first, last)中每个元素应用函数对象f,丢弃f的返回值。如果f仅是一个函数指针,说明与返回值无关;如果f是一个保留某些内部状态的对象,则该对象可以捕获一个返回值,它们结合到一起应用到该范围。最终返回值是f。
OutputIterator transform(InputIterator first, InputIterator last, OutputIterator result, UnaryFunction f); OutputIterator transform(InputIterator1 first, InputIterator1 last, InputIterator2 first2, OutputIterator result, BinaryFunction f);
transform()
对范围[first, last)中每个元素应用函数对象f。但是不丢弃调用结果。transform()将结果复制(operator=)到*result,每次复制后增加result的内容。(result指向的序列必须有足够的空间;否则,用一个插入符强迫插入来代替赋值。)- 第一种形式调用
f(*first)
,第二种形式调用f(*first1, *first2)
。返回值都是超越末尾的迭代器,迭代器指出结果输出的范围。
11. 数值算法
这些算法包含在头文件 <numeric>中,主要用来执行数值计算。
-
合计:
T accumulate(InputIterator first, InputIterator last, T result); T accumulate(InputIterator first, InputIterator last, T result, BinaryFunction f);
accumulate()
的第一种形式是一般化的求和,对迭代器i指向的[first, last)的每一个元素执行result=result+*i,result是T类型。- 第二种形式对范围内每一个元素*i应用函数
f(result, *i)
。
-
内积:
T inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init); T inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init, BinaryFunction1 op1, BinaryFunction2 op2);
-
inner_product()
算法计算范围[first1, last1)和[first2, first2 + (last1-first1) )的一个广义内积。用第一个序列中元素乘以第二个序列中“平行”的元素并对积进行累加来产生返回值。 -
参数init是内积的初始化值,可能是0也可能是任何值。
-
第二个序列至少含有第一个序列一样多的元素。
-
第二种形式对序列应用一对函数。函数op1代替加法,函数op2代替乘法。
序列{1,1,2,2}和{1,2,3,4},内积为
( 1 ∗ 1 ) + ( 1 ∗ 2 ) + ( 2 ∗ 3 ) + ( 2 ∗ 4 ) (1*1)+(1*2)+(2*3)+(2*4) (1∗1)+(1∗2)+(2∗3)+(2∗4)
第二种版本表示会进行以下运算:
init = op1(init, op2(1,1)); init = op1(init, op2(1,2)); init = op1(init, op2(2,3)); init = op1(init, op2(2,4));
-
-
广义部分和:
OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result); OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result, BinaryFunction op);
-
partial_sum()
计算一个广义部分和。创建一个新的result开始的序列,新序列中每个元素都是[first, last)范围中从第一个元素到当前选择元素的累加和。序列{1,1,2,2,3},
输出为{1,1+1,1+1+2,1+1+2+2,1+1+2+2+3}={1,2,4,6,9}。
-
第二种版本使用二元函数op代替+运算符,取得积累到那个点的所有的“合计”,并于新值结合起来。
对{1,1,2,2,3}使用
multiplies<int>()
(一种乘法op)作为对象,输出为{1,1,2,4,12}.
-
返回值指向输出范围[result, result+(last-first) )的末尾。
-
-
相邻元素差:
OutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result); OutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result, BinaryFunction op);
-
adjacent_difference()
算法计算[first, last)中相邻的元素的差。这意味着在新序列中,每个元素的值是原始序列中当前元素于前面元素的差值(第一个值不变)。序列{1,1,2,2,3}
输出{1,1-1,2-1,2-2,3-2}={1,0,1,0,1}
-
第二种形式使用二元函数op代替‘-’运算符执行“求差”。
例如使用
multiplies<int>()
(乘法代替减法)输出{1,1,2,4,6}
-
返回值指向输出范围[result, result+(last-first) )的末尾。
-
12. 基本工具
和其他算法一起使用的一些基本工具。
-
pair:
(templates in the <utility> header) template<class T1, class T2> struct pair; template<class T1, class T2> pair<T1, T2> make_pair(const T1&, const T2&);
- pair是简单将两个对象封装成一个对象的方法。
- 可以直接
insert()
一个pair到map或multimap中,对于这些容器来说pair是value_type。
-
元素个数:
(From <iterator>) difference_type distance(InputIterator first, InputIterator last);
distance()
算法计算[first, last)之间的元素个数,返回一个整数,表示first等于last之前必须增加的次数。这一过程不会解析迭代器。
-
创建迭代器:
(From <iterator>) back_insert_iterator<Container> back_inserter(Container& x); front_insert_iterator<Container> front_inserter(Container& x); insert_iterator<Container> inserter(Container& x, Iterator i);
back_inserter()
、front_inserter()
和inserter()
用来为给定容器创建迭代器,以便向容器中插入元素,而不是用operator=覆盖容器中已存在的元素(默认行为)。- 每种类型迭代器有不同的插入运算。back_insert_iterator使用
push_back()
,front_insert_iterator使用push_front()
,insert_iterator使用insert()
。
-
较小值:
const LessThanComparable& min(const LessThanComparable& a, const LessThanComparable& b); const T& min(const T& a, const T& b, BinaryPredicate binary_pred);
min()
算法返回两个参数中较小的一个,如果相等则返回第一个参数。- 第一个版本执行operator<,第二个版本将参数传给binary_pred执行比较。
-
较大值:
const LessThanComparable& max(const LessThanComparable& a, const LessThanComparable& b); const T& max(const T& a, const T& b, BinaryPredicate binary_pred);
max()
返回两个参数中较大的一个。
-
交换:
void swap(Assignable& a, Assignable& b); void iter_swap(ForwardIterator1 a, ForwardIterator2 b);
swap()
和iter_swap()
使用赋值的方法交换a和b的值。- 所有容器都有特化的swap()版本,更高效。