STL--常见的算法函数
- 非修改式序列操作
- 修改式序列操作
- copy() 复制
- copy_ backward() 逆向复制
- fill() 改填元素值
- fill_n() 改填元素值,n次
- generate() 以指定操作的运算结果填充特定范围内的元素
- generate_n() 以指定操作的运算结果填充n个元素内容
- iter_swap() 元素互换
- partition() 切割
- stable_partition() 切割并保持元素间的相对次序
- random_shuffle() 随机重排
- remove() 移除某种元素(但不删除)
- remove_copy() 移除某种元素并将结果复制到另一个容器
- remove_if() 有条件地移除某种元素
- remove_copy_if() 有条件地移除某种元素并将结果复制到另一容器
- replace() 取代某种元素
- replace_copy() 取代某种元素并将结果复制到另一容器
- replace_if() 有条件地取代某种元素
- replace_copy_if() 有条件地取代某种元素并将结果复制到另一容器
- rotate() 旋转
- rotate_copy() 旋转并将结果复制到另一容器
- reverse() 颠倒元素次序
- reverse_copy() 颠倒元素次序并将结果复制到另一容器
- transform() 以两个序列为基础,交互作用产生第三个序列
- unique() 将重复的元素折叠缩编使其唯一
- unique_copy() 将重复的元素折叠缩编使其唯一,并复制到他处
- 排序和相关操作
- binary_search() 二元搜索
- max(),min() 最大值/最小值
- max_element(),min_element() 最大值/最小值所在位置
- lexicographical_compare() 以字典排列方式做比较
- partial_sort() 局部排序
- partial_sort_copy() 局部排序并复制到他处
- set_difference() 差集
- set_intersection() 交集
- set_symmetric_difference() 对称差集
- set_union() 并集
- sort() 排序
- stable_sort() 排序并保持等值元素的相对次序
- merge() 合并两个序列
- nth_element() 重新安排序列中第n个元素的左右两端
- inplace_merge() 合并并取代(覆写)
- includes() 涵盖于
- 通用数字操作
非修改式序列操作
非修改式序列操作对区间中的每个元素进行操作。这些操作不修改容器的内容。例如,find()和for_each()就属于这一类。

find() 搜索

容器内的元素一被拿出来和特定值比较。一旦遇到相符的元素,搜索操作便结束。find()返回一个iterator,指向该元素。如果没有任何相符元素,就返回容器的end()。
#include <algorithm>
using namespace std;
int ia[7] = {1, 3, 4, 5, 7, 8, 9};
vector<string> vec(ia, ia+7);
int value = 7;
find(ia, ia+7, value);
find(vec.begin(), vec.end(), value);
find_end() 搜索某个子序列的最后一次出现地点


此算法接受两组iterator。第一组iterator标示被搜索的容器范围。第二组iteartor标示作为比对标准的一组元素序列。find_end()会找出容器内出现“比对元素序列”的最后一次位置。比对方式默认是equality运算符,但亦允许另行指定一个二元运算。如果比对成功,就返回iterator指向符合条件的位置。如果比对失败(找不到吻合序列),就返回所指定之容器范围的末尾(亦即find_end()的第二参数)。举个例子,给定字符序列Mississippi及第二序列ss,find_end()会返回一个iterator,指向Mississippi中的第二个ss子序列的第一个s位置。
#include <algorithm>
using namespace std;
int ia[7] = {7,3,3,7,6,5,8,7,2,1,3,7,6,3,8,4,3};
int seq[3] = {3, 7, 6};
// found_it指向ia[10]
found_it = find_end(ia, ia+17, seq, seq+3);
find_first_of() 搜索某些元素的首次出现地点

此算法接受两组iterator。第一组iterator标示被搜索的容器范围。第二组iteartor标示作为比对标准的一组元素序列。举个例子,如果我们想找出字符串synesthesia中的第一个元音字母,我们把第二字符串定义为aeiou。如果第一序列中存在第二序列的任一元素,find_first_of()便返回一个iterator,指向第一个出现的元素--本例为第一个e。如果第一序列中并不存在第二序列的任何元素值,便返回一个iterator,指向第一序列的末尾。可有可无的第五参数,允许你指定一个二元运算,借此改用equality运算符以外的比较方式。
#include <algorithm>
using namespace std;
string s_array[] = {"Ee", "eE", "ee", "Oo", "oo", "ee"};
string to_find[] = {"oo", "gg", "ee"};
// 返回第一次出现"ee"的位置,found_it指向&s_array[2]
found_it = find_first_of(s_array, s_array+6, to_find, to_find+3);
find_if() 在特定条件下搜索

容器内的元素会被一一施以特定的二元运算,测试是否符合条件。如果找到符合条件的元素,搜索操作便结束,并返回一个iterator指向该元素。如果没有找到符合条件的元素,就返回容器的end()。
#include <algorithm>
using namespace std;
int ia[7] = {1, 3, 4, 5, 7, 8, 9};
vector<int> vec(ia, ia+7);
int value = 7;
find_if(vec.begin(), vec.end(), bind2nd(less<int>(), value));
for_each() 对范围内的第一个元素应用某个操作

for_each()的第三参数用来表示“将依次应用于每个元素身上”的运算。这个运算不得更改元素值。如果要更改元素值,可使用transform()。指定的运算如果有返回值,该值会被忽略。
#include <algorithm>
using namespace std;
template <typename Type>
void print_elements(Type elem) { cout << elem << " "; }
int ia[7] = {1, 3, 4, 5, 7, 8, 9};
vector<int> vec(ia, ia+7);
for_each(vec.begin(), vec.end(), print_elements);
search() 搜索某个子序列


给定两个序列,search()会返回一个iterator,指向第二序列在第一序列中的出现位置。如果第二序列并不在第一序列内,这个iterator便指向第一序列的末端。以Mississippi为例,子序列iss出现了两次,search()返回的iterator会指向第一次出现位置。如果提供第五参数(可有可无),便可改用equality运算符(那是默认行为)以外的比对法。
#include <algorithm>
using namespace std;
char str[25] = "a fine and private place";
char substr[4] = "ate";
int *piter = search(str, str+25, substr, substr+4);
search_n() 搜索“连续发生n次”的子序列

search_n()会寻找序列中某个特定值“连续出现n次”的第一次出现位置。在以下例子中,我们搜寻str内“连续出现两个o”的位置,返回的iterator会指向其中的第一个o。如果容器内并无搜索目标存在,返回的iterator便指向序列的末端。如果提供第五参数(可有可无),可改用equality运算符(那是默认行为)以外的比对法。
#include <algorithm>
using namespace std;
char str[25] = "a fine and private moose";
const char oh = 'o';
int *found_str = search_n(str, str+26, 2, oh);
count() 计数

返回容器中与指定值相等的元素个数。
#include <algorithm>
using namespace std;
int ia[7] = {1, 3, 4, 5, 7, 8, 9};
vector<int> vec(ia, ia+7);
int value = 7;
cout << value << " occurs" << count(vec.begin(), vec.end(), value)
<< " times in string vector.\n";
count_if() 在特定条件下计数

返回容器中“元素值被某特定运算符求值为true”的元素个数。
#include <algorithm>
using namespace std;
class Even{
public:
bool operator()(int val)
{
return !(val%2);
}
};
int ia[7] = {1, 3, 4, 5, 7, 8, 9};
vector<int> vec(ia, ia+7);
ires = count_if(ia, ia+8, bind2nd(less<int>(), 10));
ires = count_if(vec.begin(), vec.end(), Even());
equal() 判断相等与否

如果两数列的各元素值都相同,就返回true。如果第二数列的元素比较多,多出来的元素不予考虑。默认使用equality运算符,但也可以传人一个二元的function object或function pointer,用以指定另一种比较方式。
#include <algorithm>
using namespace std;
class EqualAndOdd{
public:
bool operator()(int v1, int v2)
{
return ((v1==v2)&& (v1%2));
}
};
int ia1[] = {1, 1, 2, 3, 5, 8, 13 };
int ia2[] = {1, 1, 2, 3, 5, 8, 13, 21, 34};
vector<int> vec(ia, ia+7);
res = equal(ia, ia+7, ia2); // true
res = equal(ia, ia+7, ia2, EqualAndOdd()); // false
adjacent_find() 搜寻相邻的重复元素

默认情形下,它会搜索第一组“相邻且其值重复”的元素。可以某个二元运算符取代内置的 equality 运算符。本函数会返回一个iterator,指向两个重复元素中的第一个。
#include <algorithm>
class TwiceOver
{
public:
bool operator () (int val1, int val2)
{
return val1 == val2/2 ? true : false;
}
};
int ia[7] = {1, 4, 4, 5, 7, 8, 9};
piter = adjacent_find(ia, ia+8);
iter = adjacent_find(ia, ia+8, TwiceOver());
修改式序列操作
修改式序列操作也对区间中的每个元素进行操作。然而,顾名思义,它们可以修改容器的内容。可以修改值,也可以修改值的排列顺序。transform( ), random-shuffle()和copy()属于这一类。


copy() 复制

将第一个容器的元素一一复制到第二个容器。
#include <algorithm>
using namespace std;
int ia[7] = {1, 3, 4, 5, 7, 8, 9};
vector<int> vec(ia, ia+7);
ostream_iterator<int> ofile(cout, " ");
copy(vec.begin(), vec.end(), ofile);
vector<string> target(vec.size());
copy(vec.begin(), vec.end(), target.begin());
copy_ backward() 逆向复制

行为和copy()几乎一样,但复制操作系逆向行之。
#include <algorithm>
using namespace std;
vector<string> target(vec.size());
copy(vec.begin(), vec.end(), target.begin());#include <algorithm>
using namespace std;
int ia[7] = {1, 3, 4, 5, 7, 8, 9};
vector<int> vec(ia, ia+7);
vector<string> target(vec.size());
copy_backward(vec.begin(), vec.end(), target.begin());
fill() 改填元素值

将容器内的每个元素一一设为某特定值。
#include <algorithm>
using namespace std;
vector<int> vec(8);
fill(vec.begin(), vec.end(), 7); // 7 7 7 7 7 7 7 7
fill_n() 改填元素值,n次

将容器内的元素一设为某特定值;只设定n个元素。
#include <algorithm>
using namespace std;
int ia[7] = {1, 3, 4, 5, 7, 8, 9};
vector<int> vec(8);
int count = 5;
int value = 7;
fill_n(ia, count, value); // 7 7 7 7 7 8 9 0
fill_n(vec.begin(), count, value); // 7 7 7 7 7 0 0 0
generate() 以指定操作的运算结果填充特定范围内的元素

generate()会将指定操作的运算结果,填人序列之中。
#include <algorithm>
using namespace std;
class GenByTwo{
public:
int operator()()
{
static int seed = -1;
return seed+=2;
}
};
list<int> ilist(10);
generate(ilist.begin(), ilist.end(), GenByTwo()); // 1 3 5 7 9 11 13 15 17 19
generate_n() 以指定操作的运算结果填充n个元素内容

generate_n()会连续调用指定操作n次,并将这n次的结果填人序列的n个元素之中。
#include <algorithm>
using namespace std;
class GenByTwo{
public:
GenByTwo(int seed = 0):_seed(seed){}
int operator()()
{
return _seed+=2;
}
private:
int _seed;
};
vector<int> ivec(10);
generate_n(ivec.begin(), ivec.size(), GenByTwo(100)); // 101 103 105 107 109 111 113 115 117 119
iter_swap() 元素互换

将两个iterator所指向之元素值互换。
#include <algorithm>
using namespace std;
typedef list<int>::iterator iterator;
int ia[8] = {1, 3, 4, 5, 7, 8, 9, 10};
list<int> ilist(ia, ia+8);
iterator it1 = ilist.begin();
iterator it2 = ilist.begin()+4;
iter_swap(it1, it2);
partition() 切割

stable_partition() 切割并保持元素间的相对次序

partition()会重排诸元素的顺序,其重排依据则是根据某个一元运算的结果(true或false)。 “所有被求值为true的元素”皆被置于“所有被求值为false的元素”之前。例如,给定序列{0,1,2,3,4,5,6}及一个用以检验“元素是否为偶数”的运算操作,求值为true与求值为false的元素分别是{0,2,4,6}和{1,3,5}。虽然所有偶数保证一定会置于所有奇数之前,但在重新排定顺序之后,它们之间的相对顺序却不保证不变。唯有使用stable_partition(),才能保证容器内的元素的相对顺序不变。
#include <algorithm>
using namespace std;
class even_elem{
public:
bool operator()(int elem)
{
return elem%2 ? false : true;
}
};
int ia[12] = { 29,23,20,22,17,15,26,51,19,12,35,40 };
vector<int> ivec(ia, ia+12);
// 根据元素值是否为偶数来加以分割:
stable_partition(ivec.begin(), ivec.end(), even_elem()); //20 22 26 12 40 29 23 17 15 51 19 35
random_shuffle() 随机重排


默认情况下,random_shuffle()会根据自己的算法,随机重排各元素的位置。如果提供第三参数(可有可无),则可指定特定的随机数生成器但其返回类型必须是double且落于[0, 1]。
#include <algorithm>
using namespace std;
int ia[12] = { 29,23,20,22,17,15,26,51,19,12,35,40 };
vector<int> ivec(ia, ia+12);
random_shuffle( ivec.begin(),ivec.end()); // 26 35 51 17 29 19 12 40 23 22 20 15
remove() 移除某种元素(但不删除)

remove_copy() 移除某种元素并将结果复制到另一个容器

remove()会将序列中与特定值吻合的所有元素隔离。它并不会将符合条件的元素删去(换句话说,容器的大小不变),而是将每个不符合条件的元素依次放到可用位置上。返回的iterator指向新产生的最后一个合格元素的下一位置。
以序列{0,1,0,2,0,3,0,4}为例。我想移去数值为0的所有元素,结果将是{1,2,3,4,0,3,0,4}。1被复制到第一个位置,2被复制到第二个位置,3被复制到第三个位置,4被复制到第四个位置。第五位置上的0,是本算法的残余物,返回的iterator便指向这一位置。通常我们会将这个iterator传给erase()。数组并不适用remove()算法,因为数组不易改变大小。基于这个原因,处理数组时比较适用remove_copy()。
#include <algorithm>
using namespace std;
intia[]={0, 1, 0, 2, 0, 3, 0, 4, 0, 5};
vector<int> vec(ia, ia+10);
// remove()操作之后、erase()操作之前的vector内容:
//1 2 3 4 53 0 4 0 5
vec_iter = remove( vec.begin(), vec.end(), 0);
// erase()操作之后的vector内容:12345
vec.erase( vec_iter, vec.end());
int ia2[5];
// ia2:1 2 3 4 5
remove_copy(ia, ia+10, ia2, 0);
remove_if() 有条件地移除某种元素

remove_copy_if() 有条件地移除某种元素并将结果复制到另一容器

remove_if()会将序列之中“被特定运算求值为true”的所有元素移去。除了这一点,remove_if()/remove_copy_if()和remove()/remove_copy()的行为一致。
#include <algorithm>
using namespace std;
class EvenValue{
public:
bool operator()(int value)
{
return value%2 ? false : true;
}
};
int ia[10] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 34};
vector<int> ivec(ia, ia+12);
vector<int> :: iterator iter;
iter = remove_if(ivec.begin(), ivec.end(), bind2nd(less<int>(), 10));
ivec.erase(iter, ivec.end()); // 13 21 34
int ia2[12];
remove_copy_if(ia, ia+10, ia2, EvenValue()); // ia2: 1 1 3 5 13 21
replace() 取代某种元素

replace_copy() 取代某种元素并将结果复制到另一容器

replace()会将序列中所有“数值等于old_value”的元素,重设为new_value。
#include <algorithm>
using namespace std;
string oldval("Mr. Winnie the Pooh");
string newval("Pooh");
string sa[] = {"Christopher Robin", "Mr. Winnie the Pooh", "Piglet", "Tigger", "Eyeore"};
vector<string> vec(sa, sa+5);
//Christopher Robin Pooh Piglet Tigger Eyeore
replace(vec.begin(), vec.end(), oldval, newval);
vector<string> vec2;
//Christopher Robin Pooh Piglet Tigger Eyeore
replace_copy(vec.begin(), vec.end(), inserter(vec2, vec2.begin()), oldval, newval);
replace_if() 有条件地取代某种元素

replace_copy_if() 有条件地取代某种元素并将结果复制到另一容器

replace_if()会将序列中符合条件的所有元素,取代为new_value。所谓符合条件,是指特定比较操作的所得结果为true。
#include <algorithm>
using namespace std;
int ia[10] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 34};
int new_value = 0;
vector<int> vec(ia, ia+10);
replace_if(vec.begin(), vec.end(), bind2nd(less<int>(), 10), new_value); //0 0 0 0 0 0 0 13 21 34
rotate() 旋转

rotate_copy() 旋转并将结果复制到另一容器

rotate()接受三个iterator:first,middle,last.它会将first至middle-1及middle至last- 1所标示的各个元素相互交换。以C-Style字符串"booissl!"为例:
char ch[]="boohiss!!";
为了将它改为"hissboo!!",应该这样调用rotate():
rotate(ch, ch+3, ch+7);
下面是另一个例子:
#include <algorithm>
int ia[]={1, 3, 5, 7, 9, 0, 2, 4, 6, 8, 10};
vector<int> vec(ia, ia+ll), vec2(1l);
以下将“以0为首的后六个元素”和“以1为首的前五个元素”彼此交换:
//以中央元素(0)为轴,进行旋转操作:0 2 4 6 8 10 1 3 5 7 9
rotate(ia, ia+5, ia+1l);
以下则是将“以8为首的后两个元素”和“以1为首的前九个元素”交换:
//以倒数第二个元素(8)为轴,进行旋转操作:8 10 1 3 5 7 9 0 2 4 6
rotate_copy( vec.begin(), vec.end()-2, vec.end(), vec2.begin());
reverse() 颠倒元素次序

reverse_copy() 颠倒元素次序并将结果复制到另一容器

将容器内的元素次序予以调换。
#include <algorithm>
#include <list>
using namespace std;
string sa[] = {"Christopher Robin", "Mr. Winnie the Pooh", "Piglet", "Tigger", "Eyeore"};
list<string> slist(sa, sa+5);
list<string> slist_copy(slist.size());
reverse(slist.begin(), slist.end());
reverse_copy(slist.begin(), slist.end(), slist_copy.begin());
transform() 以两个序列为基础,交互作用产生第三个序列


transform()的第一版本会调用被传人的某个一元运算符,将它一作用于序列的每个元素身上。以序列{0,1,1,2,3,5}搭配double_val function object为例,每个元素值都会变成两倍,新产生的序列是{0,2,2,4,6,10}。第二个版本会调用被传人的某个二元运算符,应用于被传人的两个序列内“位置相同”的两两元素身上。例如,给定序列{1,3,5,9}和{2,4,6,8},并指定add_and_double function object,于是便会将对应两元素之值相加,然后再变为两倍,产生的新序列是{6,14,22,34}。第一版产生的新序列会放在第三参数(一个itearotr)所表示的起始位置上,第二版产生的新序列会放在第四参数(一个itearotr)所表示的起始位置上。
#include <algorithm>
#include <vector>
using namespace std;
int double_val(int val){ return val*2;}
int add_and_double(int val1, int val2) { return (val1 + val2)*2;}
int ia[] = {0, 1, 2, 3, 5};
vector<int> vec(5);
//第一个版本:0 2 2 4 6 10
transform(ia, ia+5, vec.begin(), double_val);
int ia1[] = {1, 3, 5, 9};
int ia2[] = {2, 4, 6, 8};
vector<int> vec2(4);
//第二个版本:6 14 22 34
transform(ia1, ia1+4, ia2, vec2.begin(), add_and_double);
unique() 将重复的元素折叠缩编使其唯一

unique_copy() 将重复的元素折叠缩编使其唯一,并复制到他处

序列中连续出现并且数值相同(以equality运算符观之)的所有元素,会被缩编成一个。可指定其他比较方式,作为数值应否缩编的判断基准。以"Mssissippi"为例,本算法产生出来的结果应该是Misisipi。由于三个i并非连续出现,所以并未像两组ss那样地遭到缩编。如果我们想要令所有重复出现的元素都缩编,应该先予以排序。
和remove()一样,容器的实际大小并未改变。从容器的第一个元素开始,每个独一无二的元素皆被放入新的可用位置上。以"Mssissippi"为例,实际运算结果是Misisipippi,最后面的ppi代表此算法的残余物。返回的iterator标示出再下来的可用位置。通常这个iterator会被我们传给erase()。由于数组并未提供erase(),所以unique()比较不适用于数组;unique_copy()比较适合数组。
#include <algorithm>
#include <vector>
using namespace std;
int ia[]={0,1,0,2,0,3,0, 4, 0, 5};
vector<int> vec(ia, ia+10);
sort(vec.begin(), vec.end());
iter = unique( vec.begin(), vec.end());
vec.erase(iter, vec.end());//vec:0 1 2 3 4 5
int ia2[10];
sort(ia, ia+10);
unique_copy(ia, ia+l0, ia2);
排序和相关操作
排序和相关操作包括多个排序函数(包括sort( ) )和其他各种函数,包括集合操作。



binary_search() 二元搜索

binary_search() 假设其处理对象已经以 less-than 运算符加以排序。如果该容器以其他方式完成排序,那么调用 binary_search() 时就得传入该二元运算符。此算法会返回 true 或 false。
#include <algorithm>
#include <list>
using namespace std;
int ia[7] = {1, 3, 4, 5, 7, 8, 9};
list<int> ilist(ia, ia+7);
bool found_it = binary_search(ilist.begin(), ilist.end(), 7);
bool found_it = binary_search(ilist.begin(), ilist.end(), 7, greater<int>());
max(),min() 最大值/最小值


返回两元素中较大(或较小)者。如果提供第三参数,就可以设定不同的比较方式。
max_element(),min_element() 最大值/最小值所在位置


返回一个iterator,指向序列中其值最大(或最小)的元素。如果提供第三参数,就可以设定不同的比较方式。
#include <algorithm>
#include <vector>
using namespace std;
int ia[12] = { 29,23,20,22,17,15,26,51,19,12,35,40 };
vector<int> ivec(ia, ia+12);
int max_val = max(ivec[4], ivec[1]);
int min_val = min(ivec[4], ivec[1]);
vector<int>::const_iterator iter;
iter = max_element(ivec.begin(), ivec.end());
iter = min_element(ivec.begin(), ivec.end());
lexicographical_compare() 以字典排列方式做比较

默认情形下,使用less-than运算符作为排序依据。如果设定第五参数,便可指定其他的排序方式。如果第一序列小于或等于第二序列,便返回true。
#include <algorithm>
#include <list>
using namespace std;
class size_compare{
public:
bool operator()(const string &a, const string &b){
return a.length() <= b.length();
}
};
string sa1[] = {"Piglet", "Pooh", "Tigger"};
string sa2[] = {"Piglet", "Pooch", "Eyeore"};
// false:'c' < 'h'
res = lexicographical_compare(sa1, sa1+3, sa2, sa2+3);
list<string> ilist1(sa1, sa1+3);
list<string> ilist2(sa2, sa2+3);
// true: Pooh < Pooch
res = lexicographical_compare(ilist1.begin(), ilist1.end(),
ilist2.begin(), ilist2.end(), size_compare());
partial_sort() 局部排序


partial_sort_copy() 局部排序并复制到他处

partial_sort()有三个参数:first,middle,last。第四个参数(可有可无)可以指定排序方式。first和middle标示出容器内的某个范围,用来存放排序结果(middle表示实际有效范围的下一个位置)。middle和last这段范围的元素,是未经排序的。例如,给定数组如下:
int ia[] = { 29,23,20,22,17,15,26,51,19,12,35,40 };
调用partial_sort()并将第六个元素标示为middle:
partial_sort( ia, ia+5,ia+12);
于是序列的前五个最小元素被排序;
{ 12, 15, 17, 19, 20, 29, 23, 22, 26, 51, 35, 40}
middle至last-1的所有元素,都未经排序,不保证呈现任何特定顺序。
set_difference() 差集

set_difference()会将“出现于第一序列内”但“未出现于第二序列内”的元素,排序后放人新序列中。假设有两个序列{0,1,2,3}和{0,2,4,6},其差集便是{1,3}。所有的集合(set)算法(后续还有三个)都接受五iterator:前两个标示出第一序列,之后两个标示出第二序列,第五个iterator标示出用来放置运算结果的起始位置。此算法假设序列已由less-than运算符加以排序,但也允许接受第六参数,指定其他排序方式。
set_intersection() 交集

set_intersection()会将两序列中皆出现的元素,加以排序并放人新序列中。例如,给定两个序列分别为{0,1,2,3}和{0,2,4,6},其交集便是{0,2}。
set_symmetric_difference() 对称差集

set_symmetric_difference()会将“出现于第一序列”但“未出现于第二序列”,以及“出现于第二序列”但“未出现于第一序列”的所有元素加以排序,放人新序列中。例如,给定两个序列{0,1,2,3}和{0,2,4,6},其对称差集为{1,3,4,6}。
set_union() 并集

set_union()所产生的新序列会包含原来的两个序列的所有元素,并加以排序。例如,给定两个序列{0,1,2,3}和{0,2,4,6},其并集为{0,1,2,3,4,6}。如果某值在两个序列中都出现,例如此例的0和2,那么仅有第一序列中的那个元素会被复制给新序列。
#include <algorithm>
#include <set>
using namespace std;
string str1[]= {"Pooh", "Piglet", "Tigger", "Eeyore" };
string str2[]={ "Pooh", "Heffalump", "Woozles" };
set<string> set1(str1, str1+4),
set2( str2, str2+3);
//用以放置每次集合运算(set operation)的结果
set<string>res;
// set_union():Eeyore Heffalump Piglet Pooh Tigger Woozles
set_union( set1.begin(),set1.end(),
set2.begin(), set2.end(), inserter( res, res.begin()));
res.clear(); //将容器清空
// set intersection():Pooh
set_intersection( set1.begin(), set1.end(), set2.begin(),
set2.end(), inserter( res, res.begin()));
res.clear();
// set_difference():Eeyore Piglet Tigger
set_difference( set1.begin(), set1.end(), set2.begin(),
set2.end(),inserter( res, res.begin()));
res.clear();
// set_symmetric_difference():
// Eeyore Heffalump Piglet Tigger Woozles
set_symmetric_difference( set1.begin(), set1.end(), set2.begin(),
set2.end(),inserter( res, res.begin()));
sort() 排序

stable_sort() 排序并保持等值元素的相对次序

默认情形下,排序算法会使用less-than运算符,将所有元素以递增方式排序。如果提供第三参数(可有可无),就可以指定其他的比较方式。stable_sort()可保持原容器内的各元素的相对次序。例如,假设我已经将许多单字以字典顺序排好了,现在我要再将它们以长度排序。于是我传入LessThan function object,用以比较两字符串的长度。如果使用sort(),无法保证“原本已排好的字典顺序”不会被破坏。
#include <algorithm>
#include <set>
using namespace std;
int ia[] = { 29,23,22,22,17,15,26,51};
stable_sort(ia, ia+8); // 15 17 22 22 23 26 29 51
vector<int> vec(ia, ia+8); // 51 29 26 23 22 22 17 15
stable_sort(vec.begin(), vec.end(), greater<int>());
merge() 合并两个序列

将两个已排序的序列合并为一个,其结果亦经排序,以第五个iterator为起始放置处。第六参数(可有可无)可设定less-than运算符以外的其他排序方式。
#include <algorithm>
#include <vector>
using namespace std;
int ia[12] = { 29, 23, 20, 22, 17, 15, 26, 51, 19, 12, 35, 40};
int ia2[12] = {74, 16, 39, 54, 21, 44, 62, 10, 27, 41, 65, 71};
vector<int> vec1(ia, ia+12);
vector<int> vec2(ia2, ia2+12);
vector<int> vec_result(vec1.size()+vec2.size());
sort(vec1.begin(), vec1.end(), greater<int>()); //51 40 35 29 26 23 22 20 19 17 15 12
sort(vec2.begin(), vec2.end(), greater<int>()); //74 71 65 62 54 44 41 39 27 21 16 10
merge(vec1.begin(), vec1.end(),
vec2.begin(), vec2.end(),
vec_result.begin(), greater<int>()
);
//74 71 65 62 54 51 44 41 40 39 35 29 27 26 23 22 21 20 19 17 16 15 12 10
nth_element() 重新安排序列中第n个元素的左右两端
nth_element()会重新安排序列的元素位置,使“小于第n个元素”的所有元素,都被重新安排于第n个元素之前,并使“大于第n个元素”的所有元素,都被重新安排于第n个元素之后。例如,给定序列如下:
int ia[] = { 29,23,20,22,17,15,26,51,19,12,35,40 };
调用nth_element()并指定ia+6(其值为26)为第n个位置:
nth_element(ia,ia+6,&ia[12]);
于是产生新序列,小于26的七个元素皆在序列左侧,大于26的四个元素皆在序列右侧:
{ 23,20,22,17,15,19,12,26,51,35,40,29 }
此算法并不保证第n个元素左右两侧的众多元素有任何特定的排序顺序。如果提供第四参数(可有可无),则可指定less-than运算符以外的其他比较方式。
inplace_merge() 合并并取代(覆写)

inplace_merge()共接受三个iterator: first,middle,last。两个输入序列分别以[first,middle)和[middle,last)标示(middle在第一序列的表示式中,代表最后一个元素的下一个位置)。这两个序列必须连续,产生的新序列会覆盖原有内容,并以first为起始位置开始放置。如果传人第四参数(可有可无),则可指定less-than运算符(这是默认行为)以外的比较操作。
#include <algorithm>
using namespace std;
int ia[20] = {29,23,20,17,15,26,51,12,35,40,74,16,54,21,44,62,10,41,65,71};
int *middle = ia+10;
int *last = ia+20;
sort(ia, middle); //12 15 17 20 23 26 29 35 40 51
sort(middle, last); // 10 16 21 41 44 54 62 65 71 74
inplace_merge(ia, middle, last); //10 12 15 16 17 20 21 23 26 29 35 40 41 44 51 54 62 65 71 74
includes() 涵盖于

如果第二序列内的每个元素皆在第一序列之中,includes()便返回true,否则返回false。两个序列都必须先经过排序。排序方式可以通过less-than运算符(这是默认行为),或是由第四参数指定。
#include <algorithm>
using namespace std;
int ia1[] = {13, 1, 21, 2, 0, 34, 5, 1, 8, 3, 21,34};
int ia2[] = {21, 2, 8, 3, 5, 1};
// 传给includes()
sort(ia1, ia1+12;)
sort(ia2, ia2+6;)
includes(ia1, ia1+12, ia2, ia2+6); // true
通用数字操作
通用数字操作包括将区间的内容累积、计算两个容器的内部乘积、计算小计、计算相邻对象差的函数。通常,这些都是数组的操作特性,因此vector是最有可能使用这些操作的容器。

accumulate() 元素累加

默认情形下,它会将容器内的所有元素相加,再加上第三个参数所指定的初值。也可以借由传入一个二元运算,取代默认的“相加”操作。
#include<numeric>
iresult = accumulate(ia, ia+8, 0);
iresult = accumulate(ilist.begin(), ilist.end(), 0, plus<int>());
inner_product() 内积

inner_product()会将两序列之元素值彼此相乘,并予以累加,然后再加上某个初始值。举个例子,给定两序列(2,3,5,8)和(1,2,3,4),本算法的运算结果便是各相应元素一一相乘之后累加起来,也就是(2x1)+(3x2)+(5x3)+(8x4)。如果再指定初值0,最后结果便是55。
第二个版本允许我们回避其默认的累加行为和相乘行为,改用我们所指定的运算。举个例子,假设使用先前所说的序列,但特别指定了减法和加法运算,结果将是各相应元素一一相加之后再彼此相减:(2+1)-(3+2)-(5+3)-(8+4)。如果初值为0,最后结果便是-28。
#include <numeric>
int ia[] = {2, 3, 5, 8};
int ia2[] = {1, 2, 3, 4};
int res = inner_product(iam ia+4, ia2, 0);
vector<int> vec(ia, ia+4);
vector<int> vec2(ia2, ia2+4);
res = inner_product(vec.begin(), vec.end(), vec2.begin(), 0, minus<int>(), plus<int>())
partial_sum() 局部总和

产生一个新序列,默认情形下,每个新元素的值皆为其自身与先前所有元素的总和。例如,给定序列{0,1,1,2,3,5,8},新产生的序列将是{0,1,2,4,7,12,20}。以第四元素为例,恰好是前三个值(0,1,1)再加上本身(2),结果为4。如果提供第四参数(可有可无),则可指定加法以外的其他运算。
#include <numeric>
#include <vector>
using namespace std;
int ires[7], ia[7] = {1, 3, 4, 5, 7, 8, 9};
vector<int> vres(7), vec(ia, ia+7);
//partial_sum():1 4 8 13 20 28 37
partial_sum( ia, ia+7, ires);
//使用multiplies<int>()的结果:1 3 12 60 420 3360 30240
partial_sum(vec.begin(), vec.end(), vres.begin(), multiplies<int>());
adjacent_difference() 相邻元素的差额

浙公网安备 33010602011771号