STL之算法

STL算法库

STL库中关于算法的内容大部分包含在<algorithm>、<numeric>和<algorithm>中,其中<algorithm>包含了大多数算法的函数,而一些关于数值处理的函数在<numeric>中。当我们需要用到函数对象相关内容时,则需要包含<function>文件。

STL算法分类

STL库中的算法大致可以分为以下几类:

STL算法分类
非更易型算法(nonmodifying algorithm)
更易型算法(modifying algorithm)
移除型算法(removing algorithm)
变序型算法(mutating algorithm)
排序算法(sorted-range algorithm)
数值算法(numeric algorithm)

当然,这样简单的分类是无法将STL中的算法完全分类开来的,会有一些算法会存在多个分类中。

非更易型算法

非更易型算法既不改动元素的顺序,也不改变元素的值。正如前面提高,迭代器是连接算法和容器的纽带,因此,它们可通过迭代器作用于所有的标准容器上

下面列出STL中的非更易型算法:

函数 作用
count() 返回元素的个数
count_if() 返回满足某一条件的元素的个数
min_element() 返回最小值
max_element() 返回最大值
minmax_element() 返回最小值和最大值元素(始于C++11)
find() 查找与目标值相等的第一个元素
find_if() 查找满足某一条件的第一个元素
find_if_not() 查找不满足某一个条件的第一个元素
search_n() 查找满足某特性的前n个元素
search() 查找某个子区间第一次出现的位置
find_end() 查找某个子区间最后一次出现的位置
find_first_of 查找数个可能元素中出现的第一个
adjacent_find() 查找连续两个相等的(或者满足某个条件)的元素
equal() 判断两个区间是否相等
is_permutation() 判断两个不定序区间是否内含相等的元素 (始于C++11)
mismatch() 返回两序列的各组对应值元素中第一对不相等的元素
lexicographical_compare() 判断在“字典序”下某序列是否小于另一序列
is_sorted() 返回区间内是否已有序(始于C++11)
is_sorted_until() 返回区间内第一个乱序元素
is_patitioned() 返回“区间内的元素是否基于某准则被分割为两组”(始于C++11)
partition_point() 返回区间内的一个分割元素,它把元素分为两个组,其中第一个组满足predicate,另一个组则不然(始于C++11)
is_heap() 返回“区间内的元素是否形成一个heap”(始于C++11)
is_heap_until() 返回“区间内第一为满足heap排序准则的元素”(始于C++11)
all_of() 返回“是否所有元素都满足某准则”(始于C++11)
any_of() 返回“是否存在元素满足某准则”(始于C++11)
none_of() 返回“是否无任何元素满足某准则”(始于C++11)

从列表中可以看出,STL中用了find和search两个单词来表示命名查找函数,看起来十分混乱。并且,他们不是分别用来表示查找元素和查找区间,而是混合使用了find和search。这使得记忆和使用十分的不便。

还有一点值得注意的是,由于string class和STL class是分开设计的,因此一些函数并不是通用的,下面列出了两者的区别:

函数作用 String STL
查找某元素第一次出现的位置 find() find()
查找某元素最后一次出现的位置 rfind() find() (利用reverse_iterator)
查找某个子区间第一次出现的位置 find() search()
查找某个子区间最后一次出现的位置 rfind() find_end()
查找某数个可能元素第一次出现的位置 find_first_of() find_first_of()
查找某数个可能元素最后一次出现的位置 find_last_of() find_first_of() (利用reverse_iterator)
n个连续元素第一次出现的位置 / search_n()

由于STL中算法众多,不可能全部进行讨论,下面挑选了几类常用的算法进行讨论,其实遵循STL标准设计的算法都是类似的。

1. 计数
计数算法为count()和count_if(),二者的函数声明如下:
count(const _InIt _First, const _InIt _Last, const _Ty& _Val)
count_if(_InIt _First, _InIt _Last, _Pr _Pred)
其中前两个参数为输入迭代器,count_if()的第三个参数指定规则。
另外,它们的返回值都是difference_type,是用以表现iterator间距的类型。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
template<typename T>
void print_container(const T &container);
int main() {
	int num;
	vector<int> vec = { 3, 2, 4, 4, 1, 5, 8, 2, 4 };
	print_container(vec);
	num=count(vec.begin(), vec.end(), 4);//count
	cout << "N(element=4): " << num << endl;
	num = count_if(vec.begin(), vec.end(),
				   [](int elem) {return elem > 4; });//count_if
	cout << "N(element>4): " << num << endl;
	num = count_if(vec.begin(), vec.end(),
		           [](int elem) {return elem % 4 == 0; });//count_if
	cout << "N(element%4=0): " << num << endl;
	return 0;
}
Element: 3 2 4 4 1 5 8 2 4
N(element=4): 3
N(element>4): 2
N(element%4=0): 4

注意这里count_if()函数的第三个参数lambda函数。

2. 最值
查找最值的函数有三个:max_element()、min_element()和minmax_element,它们分别用于查找最大、最小和最大最小值。三者的函数声明如下:
_FwdIt max_element(_FwdIt _First, _FwdIt _Last)
_FwdIt max_element(_FwdIt _First, _FwdIt _Last, _Pr _Pred)
_FwdIt min_element(_FwdIt _First, _FwdIt _Last)
_FwdIt min_element(_FwdIt _First, _FwdIt _Last, _Pr _Pred)
pair<_FwdIt, _FwdIt> minmax_element(_FwdIt _First, _FwdIt _Last)
pair<_FwdIt, _FwdIt> minmax_element(_FwdIt _First, _FwdIt _Last, _Pr _Pred)
它们默认是以"<"运算符符为比较法则,如果我们想指定比较法则可通过设定第三参数来达到目的,下面举例说明:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
template<typename T>
void print_container(const T &container);
int main() {
	int num;
	vector<int> vec = { 3, 2, -4, 4, -1, 5, -8, 2, 4 };
	print_container(vec);
	//最大值
	num = *max_element(vec.begin(), vec.end());
	cout << "Max of value: " << num << endl;
	//绝对值最大值
	num = *max_element(vec.begin(), vec.end(),
				   [](int elem1, int elem2) {return abs(elem1) < abs(elem2); });//count_if
	cout << "Max of absolute value: " << num << endl;
	//最小最大值
	auto nums = minmax_element(vec.begin(), vec.end());
	cout << "Minmax of value : " << *nums.first << "," << *nums.second << endl;

		return 0;
}
Element: 3 2 -4 4 -1 5 -8 2 4
Max of value: 5
Max of absolute value: -8
Minmax of value : -8,5

程序中依次查找序列中的最大值、绝对值的最大值以及最大最小值。
注意:这里minmax_element()函数的返回类型为pair类型。

3. 查找
查找分为查找元素查找区间

查找元素有关的算法如下:
_InIt find(_InIt _First, const _InIt _Last, const _Ty& _Val)
_InIt find_if(_InIt _First, const _InIt _Last, _Pr _Pred)
_InIt find_if_not(_InIt _First, const _InIt _Last, _Pr _Pred)
_FwdIt search_n(const _FwdIt _First, const _FwdIt _Last, const _Diff _Count, const _Ty& _Val)
_FwdIt search_n(_FwdIt _First, const _FwdIt _Last,const _Diff _Count_raw, const _Ty& _Val, _Pr _Pred)

1.三个find函数用法

int main() {
	vector<int>::iterator it;
	vector<int> vec = { 4, -2, -4, 4, 4, -1, 5, -8, 2, 4 };
	print_container(vec);
	//查找4(find)
	it = find(vec.begin(), vec.end(),4);
	if(it!=vec.end())
		cout << "Find value: " << *it << endl;
	//查找第一个大于4的元素(find_if)
	/*it = find_if(vec.begin(), vec.end(),
		bind(greater<int>(), _1, 4));
	if (it != vec.end())
		cout << "Find value>4: " << *it << endl;
	*/
	//查找第一个大于4的元素(find_if)
	it = find_if(vec.begin(), vec.end(),
		[](int val) {return val > 4; });
	if (it != vec.end())
		cout << "Find value>4: " << *it << endl;
	
	//查找第一个小于等于4的元素(find_if_not)
	it = find_if_not(vec.begin(), vec.end(),
		[](int val) {return val > 4; });
	if (it != vec.end())
		cout << "Find value<=4: " << *it << endl;
	return 0;
Element: 4 -2 -4 4 4 -1 5 -8 2 4
Find value: 4
Find value>4: 5
Find value<=4: 4

2.search_n用法:

int main() {
	vector<int>::iterator it;
	vector<int> vec = { 4, -2, -4, 4, 4, -1, 5, -8, 2, 4 };
	print_container(vec);
	it = search_n(vec.begin(), vec.end(),
		2,
		4);
	if (it != vec.end()) {
		cout << "Find 2 of 4 : " << *(it++) << " ";;
		cout << *it << endl;
	}

	it = search_n(vec.begin(), vec.end(),
				  2,
		          0,
		[](int elem,int val) {return elem < 0; });
	if (it != vec.end()) {
		cout << "Find 2 of negative val : " << *(it++) << " ";;
		cout << *it << endl;
	}
	return 0;
}
Element: 4 -2 -4 4 4 -1 5 -8 2 4
Find 2 of 4 : 4 4
Find 2 of negative val : -2 -4

注意,由于查找不一定成功,所以需在判断返回的迭代器是否有效:
if (it != vec.end()) {}

查找区间有关的算法如下:
_FwdItHaystack search(const _FwdItHaystack _First1, const _FwdItHaystack _Last1,const _FwdItPat _First2, const _FwdItPat _Last2)
_FwdItHaystack search(_FwdItHaystack _First1, const _FwdItHaystack _Last1,const _FwdItPat _First2, const _FwdItPat _Last2, _Pr _Pred)
_FwdIt1 find_end(_FwdIt1 const _First1, const _FwdIt1 _Last1,const _FwdIt2 _First2, const _FwdIt2 _Last2)
_FwdIt1 find_end(_FwdIt1 const _First1, const _FwdIt1 _Last1,const _FwdIt2 _First2, const _FwdIt2 _Last2,_Pr _Pred)

int main() {
	vector<int>::iterator it;
	vector<int> vec = { 4, -2, -4, 4, 4, -1, 5, 4, 4, -1, 5 };
	vector<int> vec1 = { 4, 4, -1, 5 };
	print_container(vec);
	print_container(vec1);
	it = search(vec.begin(), vec.end(), vec1.begin(), vec1.end());
	if (it != vec.end())
		cout << "find vec1 in vec!" << endl;
	it = search(vec.begin(), ++it, vec1.begin(), vec1.end());
	if (it != vec.end())
		cout << "find vec1 in vec again!" << endl;
	return 0;
}
Element: 4 -2 -4 4 4 -1 5 4 4 -1 5
Element: 4 4 -1 5
find vec1 in vec!
find vec1 in vec again!

4. 区间比较
关于区间比较的函数如下:
bool equal(const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _First2)
bool equal(const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _First2, _Pr _Pred)
区间比较可以比较某个区间内两容器元素是否相等或者满足某一个条件(如互为相反数)。
下面是示例:

int main() {
	bool b;
	vector<int> vec = { 4, -2, -4, 4, 4, -1, 5, 4, 4, -1, 5 };
	vector<int> vec1 = { -4, 2, 4, -4 };
	print_container(vec);
	print_container(vec1);
	b = equal(vec1.begin(), vec1.end(), vec.begin());
	if (b) cout << "true" << endl;
	else cout << "false" << endl;
	b = equal(vec1.begin(), vec1.end(), vec.begin(),
		      [](int elem1, int elem2) {return (elem1 + elem2) == 0; });
	if (b) cout << "true" << endl;
	else cout << "false" << endl;
	return 0;
}
Element: 4 -2 -4 4 4 -1 5 4 4 -1 5
Element: -4 2 4 -4
false
true

上例比较了vec1和vec的前四个元素,第一次比较对应的四个元素是否相等,而第二次比较对应的四个元素是否为相反数。得到的结果为该区间四个元素不等,但它们互为相反数。

上面的equal函数对区间内对应元素进行比较,而is_permutation()函数对区间内函数进行比较,而顺序无所谓。
该函数声明如下:
bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1,_FwdIt2 _First2)
bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1,_FwdIt2 _First2, _Pr _Pred)

int main() {
	bool b;
	vector<int> vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	vector<int> vec1 = { 2, 1, 4, 3 };
	print_container(vec);
	print_container(vec1);
	b = is_permutation(vec1.begin(), vec1.end(), vec.begin());
	if (b) cout << "true" << endl;
	else cout << "false" << endl;
	return 0;
}
Element: 1 2 3 4 5 6 7 8 9
Element: 2 1 4 3
true

从上例中可以看出,两个区间的对应元素不等,但元素却不定序相等,这时也判断为相等。

5. 有序性判断
bool is_sorted(_FwdIt _First, _FwdIt _Last)
bool is_sorted(_FwdIt _First, _FwdIt _Last, _Pr _Pred)

int main() {
	bool b;
	vector<int> vec0 = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	map<int, string> map0 = { {1, "Michael"}, {2,"Alex"}, {3, "Stark"} };
	b = is_sorted(vec0.begin(), vec0.end());
	if (b) cout << "true" << endl;
	else cout << "false" << endl; 
	b = is_sorted(map0.begin(), map0.end(),
		[](pair<int, string>elem1, pair<int, string>elem2) {
			return elem1.first < elem1.first; 
		});
	if (b) cout << "true" << endl;
	else cout << "false" << endl;
	return 0;
}

6. 存在性判断
bool any_of(const _InIt _First, const _InIt _Last, _Pr _Pred)
bool all_of(_InIt _First, _InIt _Last, _Pr _Pred)
bool none_of(const _InIt _First, const _InIt _Last, _Pr _Pred)
判断容器中存在/全为/不含满足某条件的元素。

int main() {
	bool b;
	vector<int> vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	print_container(vec);
	//存在
	b = any_of(vec.begin(), vec.end(),
		[](int elem) {return elem % 5 == 0; });
	if (b) cout << "true" << endl;
	else cout << "false" << endl;
	//全为
	b = all_of(vec.begin(), vec.end(),
		[](int elem) {return elem % 5 == 0; });
	if (b) cout << "true" << endl;
	else cout << "false" << endl;
	//不含
	b = none_of(vec.begin(), vec.end(),
		[](int elem) {return elem > 10; });
	if (b) cout << "true" << endl;
	else cout << "false" << endl;
	return 0;
}
Element: 1 2 3 4 5 6 7 8 9
true
false
true

更易型算法

非更易型算法会对容器区间的内容造成改变。包括利用迭代器进行遍历的过程中造成的改变和将元素从源区间复制到目标区间的过程中造成的改变。

下面列出STL中的更易型算法:

函数 作用
copy() 从首元素开始,复制某个区间
copy_if() 复制某个区间内满足某个条件的元素
copy_n() 复制n个元素(始于C++11)
copy_backward() 从最后一个元素开始,复制某个区间
move() 从首元素开始,搬移某个区间(始于C++11)
move_backward() 从最后一个元素开始,搬移某个区间
transform() 改动(并复制)元素,将两个区间的元素合并
merge() 合并两个区间
swap_ranges() 交换两个区间的内容
fill() 以给定值填充区间所有元素
fill_n() 以给定值填充区间中n个元素
generate 以某项操作的结果替换每一个元素
generate_n() 以某项操作的结果替换n个元素
iota() 将所有元素以一些列的递增值取代(始于C++11)
replace() 将具有某特定值的元素替换为另一个值
replace_if() 将满足某条件的元素替换为另一个值
replace_copy() 复制整个区间,并将具有某特定值的元素替换为另一个值
replace_copy_if() 复制整个区间,将满足某条件的元素替换为另一个值

下面进行简单的介绍:

1. 复制
_OutIt copy(_InIt _First, _InIt _Last, _OutIt _Dest)
_OutIt copy_if(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred)
_OutIt copy_n(_SourceTy (&_First)[_SourceSize], _Diff _Count_raw, _OutIt _Dest)
注意上述三个函数再调用时需确保目标区间由足够的空间,否则就需要使用insert iterator。

int main() {
	vector<int> vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	vector<int> vec1, vec2, vec3;
	vec1.resize(10);
	vec3.resize(10);
	cout << "vec : "; print_container(vec);
	cout << endl;
	cout << "vec1: "; print_container(vec1);
	cout << "vec2: "; print_container(vec2);
	cout << "vec3: "; print_container(vec3);
	cout << endl;

	//copy
	copy(vec.begin(), vec.begin() + 5, vec1.begin());
	cout << "vec1: "; print_container(vec1);
	//copy_if
	copy_if(vec.begin(), vec.end(), back_inserter<vector<int>>(vec2),
		[](int elem) { return elem % 2 == 0; });
	cout << "vec2: "; print_container(vec2);
	//cpy_n
	copy_n(vec.begin(), 6, vec3.begin());
	cout << "vec3: "; print_container(vec3);

	return 0;
}
vec : Element: 1 2 3 4 5 6 7 8 9

vec1: Element: 0 0 0 0 0 0 0 0 0 0
vec2: Element:
vec3: Element: 0 0 0 0 0 0 0 0 0 0

vec1: Element: 1 2 3 4 5 0 0 0 0 0
vec2: Element: 2 4 6 8
vec3: Element: 1 2 3 4 5 6 0 0 0 0

copy还可以把标准输出当作目标区间,如下:

int main() {
	vector<int> vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	copy(vec.begin(), vec.end(),
		ostream_iterator<int>(cout, " "));
	return 0;
}
1 2 3 4 5 6 7 8 9

2. 搬移
_OutIt move(_InIt _First, _InIt _Last,_OutIt _Dest)
_BidIt2 move_backward(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest)

int main() {
	vector<int> vec0 = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	vector<int> vec1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	vector<int> vec2, vec3;
	vec2.resize(10);
	vec3.resize(10);
	cout << "vec : "; print_container(vec0);
	cout << "vec1: "; print_container(vec1);
	cout << endl;
	cout << "vec2: "; print_container(vec2);
	cout << "vec3: "; print_container(vec3);
	cout << endl;

	//move
	move(vec0.begin(), vec0.end(), vec2.begin());
	move_backward(vec1.begin(), vec1.end(), vec3.end());

	cout << "vec : "; print_container(vec0);
	cout << "vec1: "; print_container(vec1);
	cout << endl;
	cout << "vec2: "; print_container(vec2);
	cout << "vec2: "; print_container(vec3);
	return 0;
}
vec : Element: 1 2 3 4 5 6 7 8 9
vec1: Element: 1 2 3 4 5 6 7 8 9

vec2: Element: 0 0 0 0 0 0 0 0 0 0
vec3: Element: 0 0 0 0 0 0 0 0 0 0

vec : Element: 1 2 3 4 5 6 7 8 9
vec1: Element: 1 2 3 4 5 6 7 8 9

vec2: Element: 1 2 3 4 5 6 7 8 9 0
vec2: Element: 0 1 2 3 4 5 6 7 8 9

3. 转换
_OutIt transform(const _InIt _First, const _InIt _Last, _OutIt _Dest, _Fn _Func)
下面是单个区间的转换:

int main() {
	vector<int> vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	vector<int> vec1;
	cout << "vec : "; print_container(vec);

	//取负,目标区间为自己
	transform(vec.begin(), vec.end(), vec.begin(), negate<int>());
	//乘10,目标区间为vec1
	transform(vec.begin(), vec.end(), back_inserter(vec1),
		bind(multiplies<int>(), _1, 10));
	cout << "vec1: "; print_container(vec1);
	cout << "cout: ";
	//取反,目标区间为标准输出
	transform(vec1.rbegin(), vec1.rend(), ostream_iterator<int>(cout, " "),
		[](int elem) {return -elem; });

	return 0;
}
vec : Element: 1 2 3 4 5 6 7 8 9
vec1: Element: -10 -20 -30 -40 -50 -60 -70 -80 -90
cout: 90 80 70 60 50 40 30 20 10

下面是两个区间的转换:

int main() {
	vector<int> vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	vector<int> vec1= { 9, 8, 7, 6, 5, 4, 3, 2, 1 };
	vector<int> vec3;
	//两区间对应元素求积,目标区间为vec3
	transform(vec.begin(), vec.end(), vec1.begin(),
				back_inserter(vec3),
				multiplies<int>());
	print_container(vec3);
	//两区间对应元素求和,目标区间为标准输出
	transform(vec.begin(), vec.end(), vec1.begin(),
				ostream_iterator<int>(cout, " "),
				plus<int>());
	return 0;
}
Element: 9 16 21 24 25 24 21 16 9
10 10 10 10 10 10 10 10 10

4. 互换元素
_FwdIt2 swap_ranges(const _FwdIt1 _First1, const _FwdIt1 _Last1, _FwdIt2 _First2)

int main() {
	vector<int> vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	vector<int> vec1= { 9, 8, 7, 6, 5, 4, 3, 2, 1 };
	print_container(vec);
	print_container(vec1);
	cout << endl;
	swap_ranges(vec.begin(), vec.end(), vec1.begin());
	print_container(vec);
	print_container(vec1);
	return 0;
}
Element: 1 2 3 4 5 6 7 8 9
Element: 9 8 7 6 5 4 3 2 1

Element: 9 8 7 6 5 4 3 2 1
Element: 1 2 3 4 5 6 7 8 9

5. 赋值
void fill(_FwdIt _First, _FwdIt _Last, const _Ty& _Val)
_OutIt fill_n(_OutIt _Dest, _Diff _Count_raw, const _Ty& _Val)
void generate(_FwdIt _First, _FwdIt _Last, _Fn _Func)
_OutIt generate_n(_OutIt _Dest, const _Diff _Count_raw, _Fn _Func)
其中,fill用于赋相同值,generator可用于赋不同值。

int main() {
	vector<string> vec;
	//fill_n
	fill_n(back_inserter(vec), 10, "Hello");
	print_container(vec);
	//fill
	fill(vec.begin(), vec.end(), "World!");
	print_container(vec);
	return 0;
}
Element: Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello
Element: World! World! World! World! World! World! World! World! World! World!

下面是generator相关用法:

int _generator() {
	static int n = 0;
	return n++;
}
int main() {
	vector<int> vec;
	//generate_n
	generate_n(back_inserter(vec), 10, _generator);
	print_container(vec);
	//generate
	generate(vec.begin(), vec.end(), _generator);
	print_container(vec);
	return 0;
}
Element: 0 1 2 3 4 5 6 7 8 9
Element: 10 11 12 13 14 15 16 17 18 19

5. 替换
void replace(const _FwdIt _First, const _FwdIt _Last, const _Ty& _Oldval, const _Ty& _Newval)
void replace_if(const _FwdIt _First, const _FwdIt _Last, _Pr _Pred, const _Ty& _Val)
其中,replace将容器中与_Oldval相等的元素全部替换为_Newval。
replace_if将满足一定条件的所有元素替换为_Val。

int main() {
	vector<int> vec = { 1, 2, 3, 4, 5, 4, 3, 2, 1 };
	print_container(vec);
	//replace
	replace(vec.begin(), vec.end(), 2, 0);
	print_container(vec);
	replace_if(vec.begin(), vec.end(),
		[](int elem) {return elem > 3; }, 0);
	print_container(vec);
	return 0;
}
Element: 1 2 3 4 5 4 3 2 1
Element: 1 0 3 4 5 4 3 0 1
Element: 1 0 3 0 0 0 3 0 1

以上。

移除型算法

移除型算法会根据元素值或者某一准则,将一个区间内的某些元素进行移除

下面列出所有的移除型算法:

算法 作用
remove() 将等于某个值的元素移除
remove_if() 将满足某个准则的元素移除
remove_copy() 将不等于某一个的元素复制到他处
remove_copy_if() 将不满足某个准则的元素复制到他处
unique() 移除毗邻的相同元素
unique_copy() 移除毗邻的相同元素并复制到他处

注意:上述算法都只是将元素移除,后面的元素会依次往前移动,但容器的元素个数不会改变。

remove()与remove_if()
_FwdIt remove(_FwdIt _First, const _FwdIt _Last, const _Ty& _Val)
_FwdIt remove_if(_FwdIt _First, const _FwdIt _Last, _Pr _Pred)

int main() {
	vector<int> vec = { 1, 2, 3, 2, 1, 2, 3, 2, 1 };
	vector<int> vec1 = vec;
	print_container(vec);
	print_container(vec1);
	//remove
	remove(vec.begin(), vec.end(), 2);
	//remove_if
	remove_if(vec.begin(), vec.end(),
		[](int elem) {return elem >= 2; });
	print_container(vec);
	print_container(vec1);
	return 0;
}
Element: 1 2 3 2 1 2 3 2 1
Element: 1 2 3 2 1 2 3 2 1
Element: 1 1 1 1 1 2 3 2 1
Element: 1 2 3 2 1 2 3 2 1

从结果可以看出,remove算法并不改变容器的元素个数,只是将元素向前移动,后面仍然是remove之前的值。

remove()和remove_if()的返回值是移除元素后的新逻辑终点,因此可以用该函数的返回值结合erase方法来将后面的元素删除

int main() {
	vector<int> vec = { 1, 2, 3, 2, 1, 2, 3, 2, 1 };
	print_container(vec);
	//erase
	vec.erase(remove(vec.begin(), vec.end(), 2),vec.end());
	print_container(vec);
	return 0;
}
Element: 1 2 3 2 1 2 3 2 1
Element: 1 3 1 3 1

从结果可以看出,erase方法将容器的元素个数改变了。

unique()
_FwdIt unique(_FwdIt _First, _FwdIt _Last)

int main() {
	vector<int> vec = { 2, 4, 2, 4, 1, 3, 3, 3, 4};
	print_container(vec);
	//unique
	vec.erase(unique(vec.begin(), vec.end()),vec.end());
	print_container(vec);
	//unique
	vec.erase(unique(vec.begin(), vec.end(), greater<int>()), vec.end());
	print_container(vec);
	return 0;
}
Element: 2 4 2 4 1 3 3 3 4
Element: 2 4 2 4 1 3 4
Element: 2 4 4 4

其中,第一次调用unique移除了毗邻的相等元素,第二次调用unique移除了比前一个元素小的元素。

变序型算法

变序型算法会改变元素的次序,但是不改变元素值。
下面列出变序型算法:

算法 作用
reverse() 将元素的次序反转
reverse_copy() 复制的同时将元素的次序反转
rotate() 旋转元素次序
rotate_copy() 复制的同时旋转元素的次序
next_permutation() 得到元素的下一个排列次序
prev_permutation() 得到元素的上一个排列次序
shuffle() 将元素的次序随机打乱(始于C++11)
random_shuffle() 将元素的次序随机打乱
partition() 改变元素次序,使“符合某准则"者移到前面
stable_partition() 与patition()类似,但保持”与准则相符“和与准则不符”之各个元素之间的相对位置
partition_copy() 改变元素次序,使“符合某准则”者移到前面,过程中并复制元素

1. 反转元素次序
void reverse(const _BidIt _First, const _BidIt _Last)
_OutIt reverse_copy(_BidIt _First, _BidIt _Last,_OutIt _Dest)
reverse算法将区间内元素全部反转次序。
list也也提供了reverse方法,该方法将指针反向而非直接将元素进行反转,因此具有更高的性能。

int main() {
	vector<int> vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9};
	print_container(vec);
	//reverse
	reverse(vec.begin(), vec.end());
	print_container(vec);
	//reverse_copy
	reverse_copy(vec.begin(), vec.end(), ostream_iterator<int>(cout, " "));
	return 0;
}
Element: 1 2 3 4 5 6 7 8 9
Element: 9 8 7 6 5 4 3 2 1
1 2 3 4 5 6 7 8 9

2. 旋转元素
_FwdIt rotate(_FwdIt _First, _FwdIt _Mid, _FwdIt _Last)
_OutIt rotate_copy(_FwdIt _First, _FwdIt _Mid, _FwdIt _Last, _OutIt _Dest)
rotate算法将区间内所有元素进行旋转(相当于循环左/右移),结果是_Mid所指元素成为第一个元素。
如下:

int main() {
	vector<int> vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9};
	print_container(vec);
	//rotate
	rotate(vec.begin(),vec.begin()+3, vec.end());
	print_container(vec);
	//rotate_copy
	rotate_copy(vec.begin(), vec.begin()+3, vec.end(), ostream_iterator<int>(cout, " "));
	return 0;
}
Element: 1 2 3 4 5 6 7 8 9
Element: 4 5 6 7 8 9 1 2 3
7 8 9 1 2 3 4 5 6

3. 排列
bool next_permutation(_BidIt _First, _BidIt _Last)
bool next_permutation(_BidIt _First, _BidIt _Last, _Pr _Pred)
bool prev_permutation(_BidIt _First, _BidIt _Last)
bool prev_permutation(_BidIt _First, _BidIt _Last, _Pr _Pred)
这几个算法是用来计算排列的,通过不断调用某个算法可以得到元素的全排列。下例:

int main() {
	vector<int> vec = { 1,2,3};
	//next_permutation
	do {
		print_container(vec);
	}while(next_permutation(vec.begin(),vec.end()));
	return 0;
}
Element: 1 2 3
Element: 1 3 2
Element: 2 1 3
Element: 2 3 1
Element: 3 1 2
Element: 3 2 1

从结果看出,1、2、3总共有六种排列的结果。

4. 打乱顺序
void shuffle(_RanIt _First, _RanIt _Last, _Urng&& _Func)
void random_shuffle(_RanIt _First, _RanIt _Last)
void random_shuffle(_RanIt _First, _RanIt _Last, _RngFn&& _RngFunc)
shuffle使用给定的随机数引擎将区间内的元素打乱;前一个random_shuffle使用一个均匀分布随机数产生器来打乱区间内的元素;后一个random_shuffle使用op来打乱区间内的元素。

int main() {
	vector<int> vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9};
	print_container(vec);
	//next_permutation
	random_shuffle(vec.begin(), vec.end());
	print_container(vec);
	sort(vec.begin(), vec.end());
	print_container(vec);
	shuffle(vec.begin(), vec.end(), default_random_engine(1));
	print_container(vec);
	return 0;
	}

5. 元素前移
_FwdIt partition(_FwdIt _First, const _FwdIt _Last, _Pr _Pred)
_BidIt stable_partition(_BidIt _First, _BidIt _Last, _Pr _Pred)
该算法将满足某准则的元素前移。如下:

int main() {
	vector<int> vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9};
	vector<int> vec1 = vec;
	print_container(vec);
	cout << endl;
	//partition
	partition(vec.begin(), vec.end(),
		[](int elem) {return elem % 2 == 0; });
	print_container(vec);
	//stable_partition
	stable_partition(vec1.begin(), vec1.end(),
		[](int elem) {return elem % 2 == 0; });
	print_container(vec1);
	return 0;
	}
Element: 1 2 3 4 5 6 7 8 9

Element: 8 2 6 4 5 3 7 1 9
Element: 2 4 6 8 1 3 5 7 9

从结果可以看出,partition将所有的偶数都移动到了前面,越靠后的元素位置越靠前;而stable_partition同样将所有的偶数都移动到了前面,但偶数元素之间仍然保持了之前的先后性。

排序算法

以下是排序有关算法:

算法 作用
sort() 对所有元素排序
stable_sort() 对所有元素排序,并保持相等元素之间的相对次序
partial_sort() 部分排序
partial_sort_copy() 部分排序并复制
nth_element() 根据某个位置进行排序
partition() 改变元素次序,使“符合某准则"者移到前面
stable_partition() 与patition()类似,但保持”与准则相符“和与准则不符”之各个元素之间的相对位置
partition_copy() 改变元素次序,使“符合某准则”者移到前面,过程中并复制元素
make_heap() 将某区间转换为一个heap
push_heap() 将元素加入一个heap
pop_heap() 从heap移除一个yuansu
sort_heap() 对heap进行排序(排序完成之后不是heap了)

1. 全排序
void sort(const _RanIt _First, const _RanIt _Last)
void sort(const _RanIt _First, const _RanIt _Last, _Pr _Pred)
void stable_sort(_BidIt _First, _BidIt _Last)
void stable_sort(_BidIt _First, _BidIt _Last, _Pr _Pred)
sort为不稳定排序,stable_sort为不稳定排序。区别在于相同元素经过排序后是否仍然保持之前的先后顺序。

int main() {
		vector<int> vec = { 1, 2, 3, 4, 5, 1, 2, 3, 4, 5};
		print_container(vec);
		sort(vec.begin(), vec.end());
		print_container(vec);
		sort(vec.begin(), vec.end(), greater<int>());
		print_container(vec);
		return 0;
	}
Element: 1 2 3 4 5 1 2 3 4 5
Element: 1 1 2 2 3 3 4 4 5 5
Element: 5 5 4 4 3 3 2 2 1 1

对于自定义类型,可通过三参数或者重载operator"<"来实现排序:
第三参数

struct Point {
	int x, y;
	Point(int a, int b) :x(a), y(b) {};
};
int main() {
	vector<Point> vec;
	vec.push_back(Point(2, 3));
	vec.push_back(Point(4, 4));
	vec.push_back(Point(-6, 3));
	print_container(vec);
	//by x
	sort(vec.begin(), vec.end(),
		[](Point p1, Point p2) {return p1.x<p2.x; });
	print_container(vec);
	//by x*x+y*y
	sort(vec.begin(), vec.end(),
		[](Point p1, Point p2) {return (p1.x*p1.x+p1.y*p1.y) < (p2.x*p2.x + p2.y*p2.y); });
	print_container(vec);
	return 0;
}
Element: 2,3 4,4 -6,3
Element: -6,3 2,3 4,4
Element: 2,3 4,4 -6,3

重载操作符"<"

struct Point {
	int x, y;
	Point(int a, int b) :x(a), y(b) {};
};
bool operator<(Point p1, Point p2) {//重载<
	return p1.x<p2.x;
}
int main() {
	vector<Point> vec;
	vec.push_back(Point(2, 3));
	vec.push_back(Point(4, 4));
	vec.push_back(Point(-6, 3));
	print_container(vec);
	sort(vec.begin(), vec.end());
	print_container(vec);
	return 0;
}
Element: 2,3 4,4 -6,3
Element: -6,3 2,3 4,4

2. 局部排序
void partial_sort(_RanIt _First, _RanIt _Mid, _RanIt _Last)
void partial_sort(_RanIt _First, _RanIt _Mid, _RanIt _Last, _Pr _Pred)
局部排序不会将所有元素进行排序,当已排出前n个最大/最小元素时排序结束。下例:

int main() {
	vector<int> vec = {2, 6, 3, 7, 8, 2, 1, 6, 4, 6, 2 , 8};
	print_container(vec);
	partial_sort(vec.begin(), vec.begin() + 5, vec.end());
	print_container(vec);
	vec.erase(vec.begin() + 5, vec.end());
	print_container(vec);
	return 0;
}
Element: 2 6 3 7 8 2 1 6 4 6 2 8
Element: 1 2 2 2 3 8 7 6 6 6 4 8
Element: 1 2 2 2 3

上例通过partial排序得到前5个值,然后通过erase将后面的元素删除。

3. 根据某个元素排序
void nth_element(_RanIt _First, _RanIt _Nth, _RanIt _Last)
void nth_element(_RanIt _First, _RanIt _Nth, _RanIt _Last, _Pr _Pred)
这里测试出了问题!

4. Heap有关算法
Heap可以视为以一定顺序形成的二叉树,它有如下两个性质:
1.首元素总是最大(最小)的。
2.增加/移除数据速度很快(O(lnN))。
STL提供了四个算法用以处理Heap:
void make_heap(_RanIt _First, _RanIt _Last)
void make_heap(_RanIt _First, _RanIt _Last, _Pr _Pred)
void push_heap(_RanIt _First, _RanIt _Last)
void push_heap(_RanIt _First, _RanIt _Last, _Pr _Pred)
void pop_heap(_RanIt _First, _RanIt _Last)
void pop_heap(_RanIt _First, _RanIt _Last, _Pr _Pred)
void sort_heap(_RanIt _First, _RanIt _Last)
void sort_heap(_RanIt _First, _RanIt _Last, _Pr _Pred)
make_heap将区间内的元素转换为heap;push_heap将end之后的最后一个元素加入原本就是heap的区间内,使整个区间形成一个heap;pop_heap将首元素移到最后一个位置,并使剩下的元素形成一个新的heap;sort_heap将一个heap转换为一个有序序列。

int main() {
	deque<int> deq = {3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 1 , 2, 3, 4, 5};
	print_container(deq);
	make_heap(deq.begin(), deq.end());//make_heap
	print_container(deq);
	pop_heap(deq.begin(), deq.end());//pop_heap
	deq.pop_back();//pop_back
	print_container(deq);
	deq.push_back(17);//push_back
	push_heap(deq.begin(), deq.end());//push_heap
	print_container(deq);
	sort_heap(deq.begin(), deq.end());//sort_heap
	print_container(deq);
	return 0;
}
Element: 3 4 5 6 7 2 3 4 5 6 1 2 3 4 5
Element: 7 6 5 6 4 3 5 4 5 3 1 2 2 4 3
Element: 6 6 5 5 4 3 5 4 3 3 1 2 2 4
Element: 17 6 6 5 4 3 5 4 3 3 1 2 2 4 5
Element: 1 2 2 3 3 3 4 4 4 5 5 5 6 6 17

上例首先将deq转换为heap,然后通过pop_heap将首元素移到最后的位置,并使用pop_back将该元素删除。之后在使用push_back在末尾添加一个17,并使用push_heap使deq形成一个heap,最后通过sort_heap将该heap转换为一个有序序列输出。

已排序区间算法

以下算法的适用范围为有序区间。

算法 作用
binary_search() 二分查找元素
includes() 判断一个区间中的元素是否包含另一个区间所有元素
lower_bound() 查找第一个大于等于给定值的元素
upper_bound() 查找第一个大于给定值的元素
equal_range() 返回等于某个值的的元素构成的区间
merge() 将两个区间进行合并
set_union() 求两个区间的并集
set_intersection() 求两个区间的交集
set_difference() 返回位于第一个区间而不位于第二个区间的元素构成的有序区间
set_symmetric_differeence() 返回两个区间的并集减去交集的元素构成的区间
inplace_merge() 将两个连贯的已排序区间进行合并
partition_point() 将区间以一定准则进行分割

1. 元素查找
bool binary_search(_FwdIt _First, _FwdIt _Last, const _Ty& _Val)
bool binary_search(_FwdIt _First, _FwdIt _Last, const _Ty& _Val, _Pr _Pred)
binary_search用于检查单个元素是否存在。

int main() {
	deque<int> deq = {3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 1 , 2, 3, 4, 5};
	print_container(deq);
	sort(deq.begin(), deq.end());
	print_container(deq);
	auto flag = binary_search(deq.begin(), deq.end(), 4);
	if (flag) cout << "4 exists in data!" << endl;
	else cout << "4 does not exist in data!" << endl;
	return 0;
}
Element: 3 4 5 6 7 2 3 4 5 6 1 2 3 4 5
Element: 1 2 2 3 3 3 4 4 4 5 5 5 6 6 7
4 exists in data!

bool includes(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2)
bool includes(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _Pr _Pred)
includes算法可用于查找多个元素是否存在于某个区间。

int main() {
	deque<int> deq = {3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 1 , 2, 3, 4, 5};
	vector<int> vec = { 5, 4, 3, 2, 1 };
	print_container(deq);
	print_container(vec);
	sort(deq.begin(), deq.end());
	sort(vec.begin(), vec.end());
	print_container(deq);
	print_container(vec);
	auto flag = includes(deq.begin(), deq.end(),vec.begin(), vec.end());
	if (flag) cout << "Exists!" << endl;
	else cout << "Does not exist!" << endl;
	return 0;
}
Element: 3 4 5 6 7 2 3 4 5 6 1 2 3 4 5
Element: 5 4 3 2 1
Element: 1 2 2 3 3 3 4 4 4 5 5 5 6 6 7
Element: 1 2 3 4 5
Exists!

这里需要注意的是两个区间必须都是已排序序列!

上述binary_search和includes算法都是返回的查找结果,如果需要得到被查找元素的位置可以通过下面两个算法:
_FwdIt lower_bound(_FwdIt _First, _FwdIt _Last, const _Ty& _Val)
_FwdIt lower_bound(_FwdIt _First, const _FwdIt _Last,const _Ty& _Val, _Pr _Pred)
_FwdIt upper_bound(_FwdIt _First, _FwdIt _Last, const _Ty& _Val)
_FwdIt upper_bound(_FwdIt _First, _FwdIt _Last,const _Ty& _Val, _Pr _Pred)
其中,lower_bound()返回指向与查找元素相等的第一个元素的迭代器,而upper_bound()则返回与查找元素相等的最后一个元素后一位置的迭代器。下例:

int main() {
	list<int> lis = {1, 2, 3, 4, 4, 4, 5, 6, 7, 8, 9};
	auto it = lower_bound(lis.begin(), lis.end(), 4);
	for (; it != lis.end(); it++)
		cout << *it << " ";
	cout << endl;
	it = upper_bound(lis.begin(), lis.end(), 4);
	for (; it != lis.end(); it++)
		cout << *it << " ";
	return 0;
}
4 4 4 5 6 7 8 9
5 6 7 8 9

从结果就可以清晰的看到lower_bound()和upper_bound()的效果有什么不同。

如果要同时获取lower_bound()和upper_bound()的结果可以利用如下函数来查找与给定元素相等的区间。
pair<_FwdIt, _FwdIt> equal_range(_FwdIt _First, _FwdIt _Last, const _Ty& _Val)
pair<_FwdIt, _FwdIt> equal_range(_FwdIt _First, _FwdIt _Last, const _Ty& _Val, _Pr _Pred)
注意这里的返回结果为pair<iterator, iterator>

int main() {
	list<int> lis = {1, 2, 3, 4, 4, 4, 5, 6, 7, 8, 9};
	print_container(lis);
	auto it = equal_range(lis.begin(), lis.end(), 4);
	lis.erase(it.first, it.second);
	print_container(lis);
	return 0;
}
Element: 1 2 3 4 4 4 5 6 7 8 9
Element: 1 2 3 5 6 7 8 9

这里通过equal_range()查找到等于4的元素的区间,然后通过list容器的erase方法将它们删除。

3. 元素合并
_DestTy * merge(_InIt1 _First1, _InIt1 _Last1,_InIt2 _First2, _InIt2 _Last2,_DestTy (&_Dest)[_DestSize])
_DestTy * merge(_InIt1 _First1, _InIt1 _Last1,_InIt2 _First2, _InIt2 _Last2,_DestTy (&_Dest)[_DestSize], _Pr _Pred)
merge算法将两个有序序列进行合并,合并后的序列仍然保持有序

int main() {
	list<int> lis = {1, 2, 3, 4, 5};
	vector<int> vec = { 3, 4, 5, 6, 7 };
	deque<int> deq;
	print_container(lis);
	print_container(vec);
	merge(lis.begin(), lis.end(), vec.begin(), vec.end(), back_inserter<deque<int>>(deq));
	print_container(deq);
	return 0;
}
Element: 1 2 3 4 5
Element: 3 4 5 6 7
Element: 1 2 3 3 4 4 5 5 6 7

void inplace_merge(_BidIt _First, _BidIt _Mid, _BidIt _Last)
void inplace_merge(_BidIt _First, _BidIt _Mid, _BidIt _Last, _Pr _Pred)
inplace_merge也是将两个有序序列进行合并,不过该两个区间首尾相连。在归并排序中我们会经常进行这种操作,用于归并相邻的区间。

int main() {
	vector<int> vec = {1, 3, 5, 6, 9, 2, 4, 7, 8, 10};
	print_container(vec);
	inplace_merge(vec.begin(), vec.begin() + 5, vec.end());
	print_container(vec);
	return 0;
}
Element: 1 3 5 6 9 2 4 7 8 10
Element: 1 2 3 4 5 6 7 8 9 10

4. 交集、并集和差集
_OutIt set_union(_InIt1 _First1, _InIt1 _Last1,_InIt2 _First2, _InIt2 _Last2, _OutIt _Dest)
_OutIt set_union(_InIt1 _First1, _InIt1 _Last1,_InIt2 _First2, _InIt2 _Last2, _OutIt _Dest, _Pr _Pred)
_OutIt set_intersection(_InIt1 _First1, _InIt1 _Last1,_InIt2 _First2, _InIt2 _Last2, _OutIt _Dest)
_OutIt set_intersection(_InIt1 _First1, _InIt1 _Last1,_InIt2 _First2, _InIt2 _Last2, _OutIt _Dest, _Pr _Pred)
set_uinon算法用于求两个有序序列的并集,set_intersection算法用于求两个有序序列的交集,它们的用法与merge类似。

int main() {
	list<int> lis = {1, 2, 3, 4, 5};
	vector<int> vec = { 3, 4, 5, 6, 7 };
	deque<int> deq,deq1;
	print_container(lis);
	print_container(vec);
	//并集
	set_union(lis.begin(), lis.end(), vec.begin(), vec.end(), back_inserter<deque<int>>(deq));
	print_container(deq);
	//交集
	set_intersection(lis.begin(), lis.end(), vec.begin(), vec.end(), back_inserter<deque<int>>(deq1));
	print_container(deq1);
	return 0;
}
Element: 1 2 3 4 5
Element: 3 4 5 6 7
Element: 1 2 3 4 5 6 7
Element: 3 4 5

_OutIt set_difference(_InIt1 _First1, _InIt1 _Last1,_InIt2 _First2, _InIt2 _Last2,_OutIt _Dest)
_OutIt set_difference(_InIt1 _First1, _InIt1 _Last1,_InIt2 _First2, _InIt2 _Last2,_OutIt _Dest, _Pr _Pred)
_OutIt set_symmetric_difference(_InIt1 _First1, _InIt1 _Last1,_InIt2 _First2, _InIt2 _Last2,_OutIt _Dest)
_OutIt set_symmetric_difference(_InIt1 _First1, _InIt1 _Last1,_InIt2 _First2, _InIt2 _Last2,_OutIt _Dest, _Pr _Pred)
set_difference算法用于求前一个序列中存在而后一个序列中不存在的元素的集合,而set_symmetric_difference算法用于求两个序列非交集元素的集合。
注意,STL中分别提供了上述算法的8个重载,这里仅列出了两个常用的形式。

int main() {
	list<int> lis = {1, 2, 3, 4, 5};
	vector<int> vec = { 3, 4, 5, 6, 7 };
	deque<int> deq,deq1;
	print_container(lis);
	print_container(vec);
	//set_difference
	set_difference(lis.begin(), lis.end(), vec.begin(), vec.end(), back_inserter<deque<int>>(deq));
	print_container(deq);
	//set_symmetric_difference
	set_symmetric_difference(lis.begin(), lis.end(), vec.begin(), vec.end(), back_inserter<deque<int>>(deq1));
	print_container(deq1);
	return 0;
}
Element: 1 2 3 4 5
Element: 3 4 5 6 7
Element: 1 2
Element: 1 2 6 7

数值算法

STL中的数值算法用于数值处理,但也不仅用于数值处理。
下面列出数值处理有关的算法:

算法 作用
accumulate() 对所有元素进行求和、乘积等运算
inner_product() 求两个区间内元素内积
adjacent_difference() 将每个元素与前一个元素进行运算
partial_sum() 将每个元素与之前所有元素进行运算

_Ty accumulate(const _InIt _First, const _InIt _Last, _Ty _Val)
_Ty accumulate(const _InIt _First, const _InIt _Last, _Ty _Val, _Fn _Reduce_op)
上述第一种形式默认对所有元素进行求和,而第二种形式可以指定运算法则。

int main() {
	vector<int> vec = {1, 3, 5, 6, 9, 2, 4, 7, 8, 10};
	print_container(vec);
	//elem1+elem2+...
	auto ret = accumulate(vec.begin(), vec.end(), 0);
	cout << "Sum(elem) = " << ret << endl;
	//elem1*elem2*...
	ret = accumulate(vec.begin(), vec.end(), 1,multiplies<int>());
	cout << "Int(elem) = " << ret << endl;
	//elem1*elem1+elem2*elem2+...
	ret = accumulate(vec.begin(), vec.end(), 0,
		[](int val, int elem) {return val + elem * elem; });
	cout << "Sum(elem*elem) = " << ret << endl;
	return 0;
}
Element: 1 3 5 6 9 2 4 7 8 10
Sum(elem) = 55
Int(elem) = 3628800
Sum(elem*elem) = 385

_Ty inner_product(const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _First2, _Ty _Val)
_Ty inner_product(_InIt1 _First1, _InIt1 _Last1,_InIt2 _First2, _Ty _Val, _BinOp1 _Reduce_op, _BinOp2 _Transform_op)
此算法用于对两个区间元素求内积,其第三个参数为初始值。

int main() {
	vector<int> vec1 = {1, 2, 3, 4 ,5};
	vector<int> vec2 = { 5, 4, 3, 2, 1 };
	cout << "vec1: "; print_container(vec1);
	cout << "vec2: "; print_container(vec2);
	//vec&vec
	auto ret = inner_product(vec1.begin(), vec1.end(), vec1.begin(), 0);
	cout << "--> (vec1|vec1) = " << ret << endl;
	//vec&vec1
	ret = inner_product(vec1.begin(), vec1.end(), vec2.begin(), 0);
	cout << "--> (vec1|vec2) = " << ret << endl;
	return 0;
}
vec1: Element: 1 2 3 4 5
vec2: Element: 5 4 3 2 1
--> (vec1|vec1) = 55
--> (vec1|vec2) = 35

_OutIt partial_sum(_InIt _First, _InIt _Last, _OutIt _Dest)
_OutIt partial_sum(const _InIt _First, const _InIt _Last, _OutIt _Dest, _BinOp _Reduce_op)
此算法第一种形式对当前元素之前的元素求部分和,第二形式可指定运算法则。

int main() {
	vector<int> vec1 = {1, 2, 3, 4 ,5};
	vector<int> vec2,vec3;
	//1, 1+2, 1+2+3, ...
	partial_sum(vec1.begin(), vec1.end(), back_inserter<vector<int>>(vec2));
	//1, 1*2, 1*2*3, ...
	partial_sum(vec1.begin(), vec1.end(), back_inserter<vector<int>>(vec3), multiplies<int>());
	print_container(vec1);
	print_container(vec2);
	print_container(vec3);
	return 0;
}
Element: 1 2 3 4 5
Element: 1 3 6 10 15
Element: 1 2 6 24 120

_OutIt adjacent_difference(const _InIt _First, const _InIt _Last, const _OutIt _Dest)
_OutIt adjacent_difference(const _InIt _First, const _InIt _Last, _OutIt _Dest, _BinOp _Func)
此算法的第一种形式用于计算相邻元素的差值;第二种形式可指定相邻元素的运算法则。

int main() {
	vector<int> vec1 = {1, 2, 3, 4 ,5};
	vector<int> vec2,vec3;
	//1, 2-1, 3-2, ...
	adjacent_difference(vec1.begin(), vec1.end(), back_inserter<vector<int>>(vec2));
	//1, 2*1, 3*2, ...
	adjacent_difference(vec1.begin(), vec1.end(), back_inserter<vector<int>>(vec3),
						multiplies<int>());
	print_container(vec1);
	print_container(vec2);
	print_container(vec3);
	return 0;
}
Element: 1 2 3 4 5
Element: 1 1 1 1 1
Element: 1 2 6 12 20

猜你喜欢

转载自blog.csdn.net/weixin_43374723/article/details/83959270
今日推荐