-
通用重新排序操作
有几个算法用指定方法对元素进行重新排序。最前面的两个 remove 和 unique 对容器重新排序,以便序列中的第一部分满足一些标准,它们返回标志这个子序列的末尾的迭代器。其 他算法,如 reverse、rotate 和 random_shuffle,重新安排整个序列。
这些算法“就地”操作,它们在输入序列本身中重新安排元素。三个重新排序算法 提供“复制”版本。算法 remove_copy、rotate_copy 和 unique_copy,将重新排序之后的序列写至目的地,而不是直接重新安排元素。
1.使用前向迭代器的重新排序算法
这些算法对输入序列进行重新排序。它们要求迭代器至少是前向迭代器。
remove(beg, end, val)
remove_if(beg, end, unaryPred)
通过用要保存的元素覆盖元素而从序列中“移去”元素。被移支的元素是 ==val 或使 unaryPred 为真的那些元素。返回一个迭代器,该迭代器指向未移去的最后一个元素的下一位 置。
例如,如果输入序列是 hello world 而 val 是 o ,则 remove 调用将序列左移两次覆盖两个元素,即字母 'o'。新序列将是 hell wrldld,返回的迭代器将指向第一个 d 之后的元素。
unique(beg, end)
unique(beg, end, binaryPred)
“移去”匹配元素的每个连续组,除了第一个之外。返回一个迭代器,该迭代器指向最后一个单一元素的下一位置。第一个版本使用 == 确定两个元素是否相同,第二个版本使用谓词测试相邻元素。
例如,如果输入序列是 boohiss,则调用 unique 之后,第一 个序列将包含 bohisss。返回的迭代器指向第一个 s 之后的元素,序列中剩余的两个元素的值是 未指定的。
rotate(beg, mid, end)
围绕由 mid 表示的元素旋转元素。mid 处的元素成为第一个 元素,从 mid + 1 到 end 的元素其次,后面是从 beg 到 mid 的范围。返回 void。
例如,给定输入序列 hissboo,如果 mid 表示字符 b,则旋转将序列重新排序为 boohiss。
2.使用双向迭代器的重新排序算法
因为这些算法向后处理输入序列,所以它们要求双向迭代器。
reverse(beg, end)
reverse_copy(beg, end, dest)
颠倒序列中的元素。reverse 就地操作,它将重新安排的元素写回输入序列。reverse_copy 将元素按逆序复制到输出迭代 器 dest。照常,程序员必须保证可以安全块使用 dest。reverse 返回 void,reverse_copy 返回一个迭代器,该迭代器指向复制到目的地的最后一个元素的下一位置。
3.写至输出迭代器的重新排序算法
这些算法要求输入序列的前向迭代器以及目的地的输出迭代器。
前面的每个通用重新排序算法都有一个 _copy 版本,这些 _copy 版本执行相同的重新排序,但是将重新排序之后的元素写至指定目的地序列,而不是改变输入序列。除 rotate_copy(它要求前向迭代器)之外,其他的都由迭代器指定输入范围。dest 迭代器必须是输出迭代器,而且,程序员也必须保证可以安全地写目的地。这些算法返回 dest 迭代器,dest 迭代器增量至指向被复制的最后元素的下一位置。
remove_copy(beg, end, dest, val)
remove_copy_if(beg, end, dest, unaryPred)
除了与 val 匹配或使 unaryPred 返回真的元素之外,其他元 素都复制到 dest。
unique_copy(beg, end, dest)
unique_copy(beg, end, dest, binaryPred)
将唯一元素复制到 dest。
rotate_copy(beg, mid, end, dest)
除了保持输入序列不变并将旋转后的序列写至 dest 之外,与 rotated 很像。返回 void。
4.使用随机访问迭代器的重新排序算法
因为这些算法按随机次序重新安排元素,所以它们要求随机访问迭代器。
random_shuffle(beg, end)
random_shuffle(beg, end, rand)
打乱输入序列中的元素。第二个版本接受随机数发生器,该函数必须接受并返回迭 代器的 difference_type 值。两个版本都返回 void。
-
排列算法
考虑下面的三个字符的序列:abc。这个序列有 6 种可能的排列: abc, acb, bac, bca, cab 和 cba。基于小于操作符按字典序列出这些排列,即,abc 是第一排列,因为它的第一个元素小于或等于其他每个排列中的首元素,而且,它的第二个元素小于首元素的任意排列中的第二个元素。类似地,acb 是下一个排列,因为它以 a 开头,a 小于其余任意排列中的首元素。以 b 开关的那些排列出现在以 c 开头的那些之前。
对于任意给定排列而言,可以指出哪个排列出现在它之前以及哪个出现在它之后。 给定排列 bca,可以指出它的前一排列是 bac,它的下一排列是 cab。序列 abc 之前没有排列,cba 之后也没有下一排列。
标准库提供两个排列算法,按字典序产生序列的排列。这些算法重新排列序列,以便(按字典序)保存给定序列的下一个或前一个排列。它们返回指出是否存在下一个或前一个排列的 bool 值。
每个算法有两个版本:一个使用元素类型的 < 操作符,另一个接受指定用于比较元素的比较关系的实参。这些算法假定序列中的元素是唯一的,也就是说,算法假定序列中没有两个元素具有相同值。
1.要求双向迭代器的排列算法
为了产生排列,必须对序列进行前向和后向处理,因此要求双向迭代器。
next_permutation(beg, end)
next_permutation(beg, end, comp)
如果序列已经是在最后一个排列中,则 next_permutation 将序列重新 排列为最低排列并返回 false;否则,它将输入序列变换为下一个排列,即字典序的下一个排列,并返回 true。第一个版本使用元素的 < 操作符比较元素,第二个版本使用指定的比较关系。
prev_permutation(beg, end)
prev_permutation(beg, end, comp)
与 next_permutation 很像,但变换序列以形成前一个排列。如果这是最小的排列,则它将序列重新排列为最大排列,并返回 false。
- 有序序列的集合算法
集合算法实现有序列的通用集合运算。
注:这些算法不同于标准 库中的 set 容器,不应该与 set 的操作相混淆,相反,这些算法提供普通顺序容器(vector、list,等等)或其他序列(如输入流)上的集合式行为.
除了 include 之外,它们也接受输出迭代器。程序员照常必须保证目的地足以保存生成的序列。这些算法返回它们的 dest 迭代器,dest 迭代器增量至指向紧接在写至 dest 的最后一个元素之后的元素。
每个算法都提供两种形式:第一种形式使用元素类型的 < 操作符比较两个输入序列中的元素,第二种形式接受一个用于比较元素的比较关系。
1.要求输入迭代器集合算法
这些算法顺序处理元素,要求输入迭代器。
includes(beg, end, beg2, end2)
includes(beg, end, beg2, end2, comp)
如果输入序列包含第二个序列中的每个元素,就返回 true;否则,返回 false。
set_union(beg, end, beg2, end2, dest)
set_union(beg, end, beg2, end2, dest, comp)
创建在任一序列中存在的元素的有序序列。两个序列中都存在的元素在输出序列中只出现一次。将序列存储在 dest 中。
set_intersection(beg, end, beg2, end2, dest)
set_intersection(beg, end, beg2, end2, dest, comp)
创建在两个序列中都存在的元素的有序序列。将序列存储在 dest 中。
set_difference(beg, end, beg2, end2, dest)
set_difference(beg, end, beg2, end2, dest, comp)
创建在第一个容器中但不在第二个容器中的元素的有序序列。
set_symmetric_difference(beg, end, beg2, end2, dest)
set_symmetric_difference(beg, end, beg2, end2, dest, comp)
创建在任一容器中存在但不在两个容器中同时存在的元素的有序序列。
- 最大值和最小值
这些算法的第一组在标准库中是独特的,它们操作值而不是序列。第二组接受一个由输入迭代器表示的序列。
min (val1, val2)
min(val1, val2, comp)
max(val1, val2)
max(val1, val2, comp)
返回 val1 和 val2 的最大值/最小值。实参必须是完全相同 的类型。使用元素类型的 < 操作符或指定的比较关系。实参和返回类型都是 const 引用,表示对象不是 复制的。
min_element(beg, end)
min_element(beg, end, comp)
max_element(beg, end)
max_element(beg, end, comp)
返回指向输入序列中最小/最大元素的迭代器。使用元素类型的 < 操作符或指定的比较关系。
1.字典序比较关系
字典序比较关系检查两个序列中的对应元素,并基于第一个不相等的元素对确定比较关系。因为算法顺序地处理元素,所以它们要求输入迭代器。如果一个序列比另一个短,并且它的元素与较长序列中对应元素相匹配,则较短的序列在字典序上较小。如果序列长短相同且对应元素匹配, 则在字典序上两者都不小于另一个。
lexicographical_compare(beg1, end1, beg2, end2)
lexicographical_compare(beg1, end1, beg2, end2, comp)
对两个序列中的元素进行逐个比较。如果第一个序列在字典序上小于第二个序列, 就返回 true;否则,返回 false。使用元素类型的 < 操作符或指定的比较关系。
- 算术算法
算术算法要求输入迭代器,如果算法修改输出,它就使用目的地输出迭代器。
这些算法执行它们的输入序列的简单算术操纵。要使用算术算法必须包含头文件 numeric。
accumulate(beg, end, init)
accumulate(beg, end, init, BinaryOp)
返回输入范围中所有值的总和。求和从指定的初始值 init 开始。返回类型是与 init 相同的类型。
给定序列 1,1,2,3,5,8 以及初始值 0,结果是 20。?第一个版本应用元素类型的 + 操作符,第二个版本应用指定的二元操作符。
inner_product(beg1, end1, beg2, init)
inner_product(beg1, end1, beg2, init, BinOp1, BinOp2)
返回作为两个序列乘积而生成的元素的总和。步调一致地检查两个序列,将来自两个序列的元素相乘,将相乘的结果求和。由 init 指定和的初值。假定从 beg2 开始的第二个序列具有至少与第一个序列一样多的元素,忽略第二个序列中超出第一个序列长度的任何元素。init 的类型决定返回类型。
第一个版本使用元素的乘操作符(*)和加操作符(+):给定两个序列 2,3,5,8 和 1,2,3,4,5,6,7,结果是初值加上下面的乘积对:
initial_value + (2 * 1) + (3 * 2) + (5 * 3) + (8 * 4)
如果提供初值 0,则结果是 55。
第二个版本应用指定的二元操作,使用第一个操作代替加而第二个操作代替乘。作为例子,可以使用 inner_product 来产生以括号括住的元素的名-值对的列表,这里从第一个输入序列获得名字,从第二个序列中获得对应的值:
// combine elements into a parenthesized, comma-separated pair
string combine(string x, string y)
{ return "(" + x + ", " + y + ")"; }
// add two strings, each separated by a comma
string concatenate(string x, string y)
{ if (x.empty()) return y; return x + ", " + y; }
cout << inner_product(names.begin(), names.end(), values.begin(), string(), concatenate, combine);
如果第一个序列包含 if、string 和 sort,且第二个序列包含 keyword、library type 和 algorithm,则输出将是
(if, keyword), (string, library type), (sort, algorithm)
partial_sum(beg, end, dest)
partial_sum(beg, end, dest, BinaryOp)
将新序列写至 dest,其中每个新元素的值表示输入范围中在它的位置之前(不包括它的位置)的所有元素的总和。第一个版本使用元素类型 + 操作符,第二个版本应用指定的二元操作符。程序员必须保证 dest 至少与输入序列一样大。返回 dest,dest 增量到指向被写入的最后元素的下一位置。
给定输入序列 0,1,1,2,3,5,8,目的序列将是 0,1,2,4,7,12,20。例如,第四个元素是前三值(0,1,1)的部分和加上它自己的值(2),获得值 4。
adjacent_difference(beg, end, dest)
adjacent_difference(beg, end, dest, BinaryOp)
将新序列写至 dest,其中除了第一个元素之外每个新元素表示当前元素和前一元素的差。第一个版本使用元素类型的 - 操作符,第二个版本应用指定的二元操作。程序员必须保证 dest 至少与输入序列一样大。
给定序列 0,1,1,2,3,5,8,新序列的第一个元素是原序列第一个元素的副本:0,第二个元素是前两个元素的差:1,第三个元素是原序列第三个元素和第二个元素的差,为 0,以此类推,新序列是 0,1,0,1,1,2,3。