《Thinking in C++》笔记:STL算法

《Thinking in C++> STL算法总结笔记。

STL算法目录

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) (11)+(12)+(23)+(24)

      第二种版本表示会进行以下运算:

      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()版本,更高效。
C++编程思想》(第1版) 荣获1996年度《软件开发》杂志的图书震撼大奖 (Jolt Award),成为该年度最佳图书。 本书内容: ·介绍实用的编程技术和最佳的实践方法,解决C++开发中最困难的课题 ·深入研究标准C++库的功能,包括:字符串、输入输出流、STL算法和容器 ·讲述模板的现代用法,包括模板元编程 ·解开对多重继承的困惑,展示RTTI的实际使用 ·深入探究异常处理方法,清晰解释异常安全设计 ·介绍被认为是标准C++下一版特征之一的多线程处理编程技术,并提供最新研究成果 ·对书中包含的所有示例代码都提供免费下载,这些代码段经过多个软件平台和编译器(包括基于Windows/Mac/Linux的GNU C++编译器) 的测试,稳定可靠。 在本书作者的个人网站www.BruceEckel.com上提供: ·本书的英文原文、源代码、练习解答指南、勘误表及补充材料 ·本书相关内容的研讨和咨询 ·本书第1卷及第2卷英文电子版的免费下载链接。 【目录信息】 第一部分 建立稳定的系统 第1章 异常处理 2 1.1 传统的错误处理 2 1.2 抛出异常 4 1.3 捕获异常 5 1.3.1 try块 5 1.3.2 异常处理器 5 1.3.3 终止和恢复 6 1.4 异常匹配 7 1.4.1 捕获所有异常 8 1.4.2 重新抛出异常 8 1.4.3 不捕获异常 9 1.5 清理 10 1.5.1 资源管理 11 1.5.2 使所有事物都成为对象 12 1.5.3 auto_ptr 14 1.5.4 函数级的try块 15 1.6 标准异常 16 1.7 异常规格说明 18 1.7.1 更好的异常规格说明 21 << 查看详细目录 book53.part1.rar http://www.shubulo.com/attachment.php?aid=35 book53.part2.rar http://www.shubulo.com/attachment.php?aid=36 Thinking in C++(2nd) http://download.chinaitlab.com/program/files/1790.html http://www.7880.com/Download/Thinking-in-C++-9836.html参考资料:http://www.shubulo.com/viewthread.php?tid=32&extra=page=2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吉拉尔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值