【《Thinking in C++》 STL算法总结笔记】

目录

0.算法概览

1.迭代器形式:

2.填充和生成

3. 计数

4. 操作序列

5. 查找和替换

6. 比较范围

7. 删除元素:

8. 对已排序的序列进行排序和运算

9. 堆运算

10. 对某一范围内的所有元素进行运算

11. 数值算法

12. 基本工具


0.算法概览

  1. fill(),                                      为[first, last)每个元素赋值value。
  2. fill_n(),                               由first开始的n个元素赋值value。
  3. generate(),                        用发生器为[first, last)的每个元素生成一个值。
  4. generate_n(),                     为first开始的n个元素生成一个值。
  5. count(),                              范围内等于value的个数。
  6. count_if(),                          范围内是判定函数为真的个数。
  7. copy(),                               从[first, last)复制序列到destination。
  8. copy_backward(),              反向复制元素。
  9. reverse(),                           倒置源序列
  10. reverse_copy(),                  源序列不变,导致结果复制到destination。
  11. swap_ranges(),                  交换相等大小两个范围的内容
  12. rotate(),                     把[first, middle)范围元素移到序列末尾,[middle, last)移到序列开始。
  13. rotate_copy(),                    不改变原始序列,轮换结果复制到destination。
  14. next_permutation(),              后继排列
  15. prev_permutation(),           前驱排列
  16. random_shuffle(),               重新排列元素(混洗)
  17. partition(),                           将满足判定函数的元素移动到序列开头。
  18. stable_partition(),                稳定划分,保持相对位置不变
  19. find(),                                  查找value第一次出现的位置
  20. find_if(),                              查找使判定函数为真的元素。
  21. adjacent_find(),                  查找两个邻近的相等元素。
  22. find_first_of(),                     在第二个范围内查找与第一个范围内的某个元素相等的元素。
  23. search(),                             查找第二个序列第一次出现在第一个序列的位置。
  24. find_end(),                          查找第二个序列最后一次出现在第一个序列的位置。
  25. search_n(),                         在范围内查找一组共count个连续的值。
  26. min_element(),                   最小值首次出现的位置。
  27. max_element(),                  最大值首次出现的位置。
  28. replace(),                            旧值替换为新值。
  29. replace_if(),                         使判定函数为真的值替换为新值。
  30. replace_copy(),                   不修改原始序列,替换旧值放入result。
  31. replace_copy_if(),               不修改原始序列,替换使判定函数为真的值放入result。
  32. equal(),                               判断两个范围内元素是否完全相同。
  33. lexicographical_compare(),第一个范围是否“字典序小于”第二个范围。
  34. mismatch(),                         两个范围不匹配的位置。
  35. remove(),                            删除等于value的元素。
  36. remove_if(),                        删除使判定函数为真的元素。
  37. remove_copy(),                  不改变源序列。
  38. remove_copy_if(),              不改变源序列。
  39. unique(),                             删除相邻的相等值(副本)。
  40. unique_copy(),                    不改变源序列。
  41. sort(),                                  升序排序。
  42. stable_sort(),                      稳定升序排序。
  43. partital_sort(),                     对一定元素进行排序,使其有序放入[first, middle)中。
  44. partital_sort_copy(),           不改变源序列。
  45. nth_element(),                    使[first, nth]内所有元素都满足二元判定函数。
  46. binary_search(),                 告诉value是否出现在有序序列中。
  47. lower_bound(),                    value第一次出现的位置。
  48. upper_bound(),                   超越value最后出现的位置。
  49. equal_range(),                    value第一次和超越最后一次出现的位置。
  50. merge(),                              升序合并序列。
  51. inplace_merge(),                 升序合并同一序列的两个范围。
  52. includes(),                           判断第二个范围是否是第一个范围子集。
  53. set_union(),                        并集。
  54. set_intersection(),               交集。
  55. set_difference(),                  差。
  56. set_symmetric_difference(),对称差。
  57. make_heap(),                      建堆。
  58. push_heap(),                       向[first, last-1)堆中增加元素*(last-1)并放入合适位置。
  59. pop_heap(),                         将最大元素*first放入位置(last-1)并调整堆。
  60. sort_heap(),                         堆排序,使堆转为有序序列,不稳定排序。
  61. for_each(),                           遍历运算,丢弃调用返回值。
  62. transform(),                          遍历运算,保留调用返回值。
  63. accumulate(),                      合计。
  64. inner_product(),                  广义内积。
  65. partial_sum(),                      广义部分和。
  66. adjacent_difference(),        相邻元素差。
  67. make_pair(),                       两个对象封装为一个对象。
  68. distance(),                           [first, last)之间的元素个数。
  69. back_inserter(),                   迭代器。
  70. front_inserter(),                   迭代器。
  71. inserter(),                            迭代器。
  72. min(),                                  较小值。
  73. max(),                                 较大值。
  74. swap(),                               交换a和b。

1.迭代器形式:

  1. InputIterator。一个只允许单个向序列输入迭代器,前向传递使用operator++和operator*。可以通过operator==和operator!=检测输入迭代器,这是约束的范围。
  2. OutputIterator。一个只允许单个向序列写入的元素的输出迭代器,前向传递使用operator++和operator*。可以持有无限个对象,不需要结尾检查,可以和ostream(通过ostream_iterator)一起使用,也普遍使用插入迭代器(back_insert()返回的迭代器类型。
  3. ForwardIterator。仍然仅用operator++前向移动,但是可以同时进行读和写和判断相等。
  4. BidirectionalIterator。支持ForwardIterator的全部操作,还增加了operator--运算,支持后向移动。
  5. 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()指出两个范围从哪里开始不同。为了完成这一工作,必须知道:
  1. 第一个范围内出现不匹配元素的位置
  2. 第二个范围内出现不匹配元素的位置。

将这两个迭代器一起装入一个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. 所有在集合1而不在集合2中的元素。
  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()版本,更高效。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值