C++ STL常用算法:遍历、查找、排序、拷贝与替换、算术生成、集合算法

文章目录


0 STL算法

STL算法主要由<algorithm> <functional> <numeric>头文件组成。
<algorithm>:包括遍历、查找、排序、比较、交换、复制、修改等操作的函数模板。
<functional>:包括函数对象/仿函数相关的类模板。
<numeric>:体积较小,仅包括简单数学运算相关的函数模板。


1 常用遍历算法【for_each、transform】

算法简介
for_each:遍历容器元素及统一逻辑处理。
transform:将源容器的元素全部拷贝至目标容器。


1.1 for_each【遍历容器元素及统一逻辑处理】

作用:遍历容器元素及统一逻辑处理。

注:使用for_each算法时,需包含头文件include <algorithm>

函数原型:
for_each(iterator begin, iterator end, _func);

参数解释
begin:迭代器起始位置;
end:迭代器结束位置;
_func:对当前所遍历的容器元素的处理。
①普通回调函数;
②函数对象/仿函数;
③匿名函数(lambda表达式)。

示例

#include <iostream>
using namespace std;

#include <vector>
#include <algorithm>	//使用for_each算法

//普通回调函数
void print(int val) {
	cout << val << " ";
}

//函数对象/仿函数
class Printer{
public:
	void operator()(int val) {
		cout << val << " ";
	}
};

int main() {
	vector<int> v;

	v.push_back(9);
	v.push_back(1);
	v.push_back(7);
	v.push_back(6);
	v.push_back(3);

	/* 遍历容器元素 */
	//1.for_each算法 + 普通回调函数————传递函数名
	for_each(v.begin(), v.end(), print);		//9 1 7 6 3
	
	//2.for_each算法 + 函数对象/仿函数————传递匿名函数对象
	for_each(v.begin(), v.end(), Printer());	//9 1 7 6 3
	
	//3.for_each算法 + 匿名函数(lambda表达式)
	for_each(v.begin(), v.end(), [](int val) {cout << val << " "; });	//9 1 7 6 3

	/* 对容器元素的统一逻辑处理 */ 
	//全部容器元素的值减1后输出
	for_each(v.begin(), v.end(), [](int val) {cout << val - 1 << " "; });	//8 0 6 5 2

	return 0;
}

1.2 transform【将源容器的元素全部拷贝至目标容器】

作用:将源容器的元素全部拷贝至目标容器。

注1:使用transform算法时,需包含头文件include <algorithm>
注2:使用transform算法时,需为目标容器提前开辟内存空间,如dest.resize(src.size());,否则程序运行时崩溃。

函数原型
transform(iterator begin1, iterator end1, iterator begin2, _func);

参数解释
begin1:源容器迭代器起始位置;
end1:源容器迭代器结束位置;
begin2:目标容器迭代器起始位置;
_func:对当前遍历容器元素的逻辑运算处理。
①普通回调函数;
②函数对象/仿函数;
③匿名函数(lambda表达式)。

示例

#include <iostream>
using namespace std;

#include <vector>
#include <algorithm>	//使用transform算法

//普通回调函数
int print(int val) {
	//元素值加10
	return val + 10;
}

//函数对象/仿函数
class Printer {
public:
	int operator()(int val) {
		//直接返回元素
		return val;
	}
};

int main() {
	vector<int> src;

	for(int i = 0; i < 5; i++){
		src.push_back(i);
	}

	/* 拷贝容器的全部元素,必须为目标容器提前开辟内存空间 */
	vector<int> dest;
	dest.resize(src.size());

	//1.transform算法 + 普通回调函数————传递函数名
	transform(src.begin(), src.end(), dest.begin(), print);
	for_each(dest.begin(), dest.end(), [](int val) {cout << val << " "; });	//10 11 12 13 14

	//2.transform算法 + 函数对象/仿函数————传递匿名函数对象
	transform(src.begin(), src.end(), dest.begin(), Printer());
	for_each(dest.begin(), dest.end(), [](int val) {cout << val << " "; });	//0 1 2 3 4

	//3.transform算法 + 匿名函数(lambda表达式)
	transform(src.begin(), src.end(), dest.begin(), [](int val) {return val + 20; });
	for_each(dest.begin(), dest.end(), [](int val) {cout << val << " "; });	//20 21 22 23 24

	return 0;
}

2 常用查找算法【find、find_if、adjacent_find、binary_search、count、count_if】

算法简介
find:查找指定元素是否存在。
find_if按条件查找元素是否存在。
adjacent_find:查找相邻且重复的元素
binary_search:二分查找判断元素是否存在。
count :统计元素个数。
count_if按条件统计元素个数。


2.1 find【查找指定元素是否存在】

作用:查找指定元素是否存在:存在则返回第1次匹配指定元素的迭代器位置;不存在则返回结束迭代器end()

注1:使用find算法时,需包含头文件include <algorithm>
注2:查找自定义数据类型的元素时,需在自定义数据类型的类中,重载运算符operator==,告知find算法应如何比较两个自定义数据类型的对象。

函数原型
find(iterator begin, iterator end, value);

参数解释
begin:迭代器起始位置;
end:迭代器结束位置;
value:待查找的元素。

示例

#include <iostream>
using namespace std;

#include <vector>
#include <algorithm>	//使用find算法

//查找内置数据类型元素
void func1() {
	vector<int> v;

	v.push_back(9);
	v.push_back(1);
	v.push_back(7);
	v.push_back(6);
	v.push_back(3);

	vector<int>::iterator pos = find(v.begin(), v.end(), 6);

	if (pos != v.end()) {
		cout << "目标元素存在:" << *pos << endl;	//6
	}
	else {
		cout << "目标元素不存在.." << endl;
	}
}


class Person {
public:
	string name;
	int age;

	Person(string name, int age) {
		this->name = name;
		this->age = age;
	}

	//重载operator==运算符
	bool operator==(const Person& p) {
		return this->name == p.name && this->age == p.age;
	}
};

//查找自定义数据类型元素,需重载operator==运算符
void func2() {
	vector<Person> v;
	Person p1("Tom", 16);
	Person p2("Jerry", 18);
	Person p3("Jack", 20);
	Person p4("Lucy", 22);

	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);
	
	Person person("Lucy", 22);

	vector<Person>::iterator pos = find(v.begin(), v.end(), person);

	if (pos != v.end()) {
		cout << "目标元素存在:" << endl;
		cout << "姓名:" << (*pos).name << ",年龄:" << pos->age << endl;
	}
	else {
		cout << "目标元素不存在.." << endl;
	}
}

int main() {
	func1();
	func2();

	return 0;
}

2.2 find_if【按条件查找元素是否存在】

作用按条件查找元素是否存在:存在则返回第1次匹配指定条件的迭代器位置;不存在则返回结束迭代器end()

注1:使用find_if算法时,需包含头文件include <algorithm>
注2:查找自定义数据类型的元素时,需指定查询条件:①普通回调函数;②谓词(返回类型为bool的仿函数);③匿名函数(lambda表达式)。
注3:按查询使用find,按条件查询使用find_if

函数原型
find_if(iterator begin, iterator end, _Pred);

参数解释
begin:迭代器起始位置;
end:迭代器结束位置;
_Pred:指定查询的条件。
①普通回调函数;
谓词(返回类型为bool的仿函数);
③匿名函数(lambda表达式)。

示例

#include <iostream>
using namespace std;

#include <vector>
#include <algorithm>	//使用find_if算法

//回调函数
bool lessThanFive(int val) {
	return val < 5;
}

//谓词(返回类型为bool的仿函数/函数对象)
class LessThanFive {
public:
	bool operator()(int val) {
		return val < 5;
	}
};

//查找内置数据类型元素
void func1() {
	vector<int> v;

	v.push_back(9);
	v.push_back(1);
	v.push_back(7);
	v.push_back(6);
	v.push_back(3);

	//回调函数
	//vector<int>::iterator pos = find_if(v.begin(), v.end(), lessThanFive);
	
	//谓词
	//vector<int>::iterator pos = find_if(v.begin(), v.end(), LessThanFive());
	
	//匿名函数(lambda表达式)
	vector<int>::iterator pos = find_if(v.begin(), v.end(), [](int val) {return val < 5;});

	if (pos != v.end()) {
		cout << "目标元素存在:" << *pos << endl;	//1
	}
	else {
		cout << "目标元素不存在.." << endl;
	}
}


class Person {
public:
	string name;
	int age;

	Person(string name, int age) {
		this->name = name;
		this->age = age;
	}
};

//回调函数
bool greaterThan20(const Person &p) {
	return p.age > 20;
}

//谓词(返回类型为bool的仿函数/函数对象)
class GreaterThan20 {
public:
	bool operator()(const Person& p) {
		return p.age > 20;
	}
};

//查找自定义数据类型元素,需重载operator==运算符
void func2() {
	vector<Person> v;
	Person p1("Tom", 16);
	Person p2("Jerry", 18);
	Person p3("Jack", 20);
	Person p4("Lucy", 22);

	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);

	//回调函数
	//vector<Person>::iterator pos = find_if(v.begin(), v.end(), greaterThan20);

	//谓词
	//vector<Person>::iterator pos = find_if(v.begin(), v.end(), GreaterThan20());

	//匿名函数(lambda表达式)
	vector<Person>::iterator pos = find_if(v.begin(), v.end(), [](const Person &p) {return p.age > 20; });

	if (pos != v.end()) {
		cout << "目标元素存在:" << endl;
		cout << "姓名:" << (*pos).name << ",年龄:" << pos->age << endl;	//姓名:Lucy,年龄:22
	}
	else {
		cout << "目标元素不存在.." << endl;
	}
}

int main() {
	//func1();
	func2();

	return 0;
}

2.3 adjacent_find【查找相邻且重复的元素】

作用:查找相邻且重复的元素是否存在:存在则返回相邻且重复元素中第1个元素的迭代器位置;不存在则返回结束迭代器end()

函数原型
adjacent_find(iterator begin, iterator end);

参数解释
begin:迭代器起始位置;
end:迭代器结束位置。

示例

#include <iostream>
using namespace std;

#include <vector>
#include <algorithm>	//使用adjacent_find算法

//查找相邻且重复元素
void func1() {
	vector<int> v;

	v.push_back(9);	//重复元素,但不相邻
	v.push_back(1);
	v.push_back(9);
	v.push_back(7);
	v.push_back(6);
	v.push_back(3);	//相邻且重复元素
	v.push_back(3);

	//adjacent_find算法
	vector<int>::iterator pos = adjacent_find(v.begin(), v.end());
	if (pos != v.end()) {
		cout << "存在相邻且重复元素:" << *pos << endl;	//3
	}
	else {
		cout << "不存在相邻且重复元素.." << endl;
	}
}

int main() {
	func1();

	return 0;
}

2.4 binary_search【二分查找法判断指定元素是否存在】

作用二分查找法判断指定元素是否存在:存在则返回true;不存在则返回false

注1:binary_search算法的查找效率高,但必须对有序序列使用,无序序列中不可用。
注2:使用binary_search算法时,需包含头文件include <algorithm>

函数原型
bool binary_search(iterator begin, iterator end, value);

参数解释
begin:迭代器起始位置;
end:迭代器结束位置;
value:待查找的元素。

示例

#include <iostream>
using namespace std;

#include <vector>
#include <algorithm>	//使用binary_search算法

//对有序序列使用二分查找
int main() {
	vector<int> v;

	v.push_back(9);
	v.push_back(1);
	v.push_back(7);
	v.push_back(6);
	v.push_back(3);

	//只能对有序序列使用二分查找
	sort(v.begin(), v.end());

	bool flag = binary_search(v.begin(), v.end(), 6);
	cout << (flag ? "存在" : "不存在") << endl;	//存在

	return 0;
}

2.5 count【统计指定元素的个数】

作用:统计指定元素的个数。

注1:使用count算法时,需包含头文件include <algorithm>
注2:统计自定义数据类型元素的个数时,需在自定义数据类型的类中,重载运算符operator==,告知count算法应如何比较两个自定义数据类型的对象。

函数原型
count(iterator begin, iterator end, value);

参数解释
begin:迭代器起始位置;
end:迭代器结束位置;
value:待查找的元素。

示例

#include <iostream>
using namespace std;

#include <vector>
#include <algorithm>	//使用count算法

//统计内置数据类型元素的个数
void func1() {
	vector<int> v;

	v.push_back(9);
	v.push_back(1);
	v.push_back(1);
	v.push_back(1);
	v.push_back(7);
	v.push_back(6);
	v.push_back(3);

	int total = count(v.begin(), v.end(), 1);
	cout << "元素1的个数:" << total << endl;	//3
}

class Person {
public:
	string name;
	int age;

	Person(string name, int age) {
		this->name = name;
		this->age = age;
	}

	//重载operator==运算符
	//与目标对象age属性相等
	bool operator==(const Person& p) {
		return this->age == p.age;
	}
};

//统计自定义数据类型元素的个数
void func2() {
	vector<Person> v;
	Person p1("Tom", 16);
	Person p2("Jerry", 18);
	Person p3("Jack", 22);
	Person p4("Lucy", 22);

	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);

	Person person("Michael", 22);

	int total = count(v.begin(), v.end(), person);
	cout << "与Michael同龄的Person对象个数:" << total << endl;	//2
}

int main() {
	func1();
	func2();

	return 0;
}

2.6 count_if【按条件统计指定元素的个数】

作用按条件统计指定元素的个数。

注1:使用count_if算法时,需包含头文件include <algorithm>
注2:按统计使用count,按条件统计使用count_if

函数原型
count_if(iterator begin, iterator end, _Pred);

参数解释
begin:迭代器起始位置;
end:迭代器结束位置;
_Pred:指定统计的条件。
①普通回调函数;
谓词(返回类型为bool的仿函数);
③匿名函数(lambda表达式)。

示例

#include <iostream>
using namespace std;

#include <vector>
#include <algorithm>	//使用count_if算法

//回调函数
bool lessThanFive(int val) {
	return val < 5;
}

//谓词(返回类型为bool的仿函数/函数对象)
class LessThanFive {
public:
	bool operator()(int val) {
		return val < 5;
	}
};

//按条件统计内置数据类型元素的个数
void func1() {
	vector<int> v;

	v.push_back(9);
	v.push_back(1);
	v.push_back(7);
	v.push_back(6);
	v.push_back(3);

	/* 统计值小于5的元素 */
	//回调函数
	//int total = count_if(v.begin(), v.end(), lessThanFive);

	//谓词
	//int total = count_if(v.begin(), v.end(), LessThanFive());

	//匿名函数(lambda表达式)
	int total = count_if(v.begin(), v.end(), [](int val) {return val < 5; });

	cout << "值小于5的元素个数:" << total << endl;		//2
}


class Person {
public:
	string name;
	int age;

	Person(string name, int age) {
		this->name = name;
		this->age = age;
	}
};

//回调函数
bool ageGreaterThan20(const Person& p) {
	return p.age > 20;
}

//谓词(返回类型为bool的仿函数/函数对象)
class AgeGreaterThan20 {
public:
	bool operator()(const Person& p) {
		return p.age > 20;
	}
};

//按条件统计自定义数据类型元素的个数
void func2() {
	vector<Person> v;
	Person p1("Tom", 16);
	Person p2("Jerry", 18);
	Person p3("Jack", 20);
	Person p4("Lucy", 22);

	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);

	//回调函数
	//int total = count_if(v.begin(), v.end(), ageGreaterThan20);

	//谓词
	//int total = count_if(v.begin(), v.end(), AgeGreaterThan20());

	//匿名函数(lambda表达式)
	int total = count_if(v.begin(), v.end(), [](const Person& p) {return p.age > 20; });

	cout << "年龄大于20的Person对象个数:" << total << endl;	//1
}

int main() {
	//func1();
	func2();

	return 0;
}

3 常用排序算法【sort、random_shuffle、merge、reverse】

算法简介
sort:对容器元素排序。
random_shuffle:对指定范围的容器元素随机排序,即洗牌
merge合并两个容器的元素,并存储至新容器中。
reverse反转的容器元素。


3.1 sort【对容器元素排序】

作用:对容器元素排序。

注:使用sort算法时,需包含头文件include <algorithm>

函数原型
sort(iterator begin, iterator end, _Pred);

参数解释
begin:迭代器起始位置;
end:迭代器结束位置;
_Pred可选项,默认升序排序;可指定自定义排序规则。
①普通回调函数;
谓词(返回类型为bool的仿函数);
③匿名函数(lambda表达式)。
④内建函数对象/关系仿函数(bool greater<T>bool less<T>)。

示例

#include <iostream>
using namespace std;

#include <vector>
#include <algorithm>	//使用sort算法

//回调函数
bool myCompare(int val1, int val2) {
	return val1 > val2;
}

//函数对象/仿函数
class MyCompare {
public:
	//重载函数调用运算符()
	bool operator()(int val1, int val2) {
		return val1 > val2;
	}
};

//sort排序
int main() {
	vector<int> v;

	v.push_back(9);
	v.push_back(1);
	v.push_back(7);
	v.push_back(6);
	v.push_back(3);

	//默认升序排序
	sort(v.begin(), v.end());
	for_each(v.begin(), v.end(), [](int val) {cout << val << " "; });	//1 3 6 7 9

	/* 降序排序 */
	//1.回调函数实现降序排序
	sort(v.begin(), v.end(), myCompare);
	for_each(v.begin(), v.end(), [](int val) {cout << val << " "; });	//9 7 6 3 1

	//2.仿函数实现降序排序
	sort(v.begin(), v.end(), MyCompare());
	for_each(v.begin(), v.end(), [](int val) {cout << val << " "; });	//9 7 6 3 1

	//3.匿名函数(lambda表达式)实现降序排序
	sort(v.begin(), v.end(), [](int val1, int val2) {return val1 > val2; });
	for_each(v.begin(), v.end(), [](int val) {cout << val << " "; });	//9 7 6 3 1

	//4.内建函数对象实现降序排序
	sort(v.begin(), v.end(), greater<int>());
	for_each(v.begin(), v.end(), [](int val) {cout << val << " "; });	//9 7 6 3 1

	return 0;
}

3.2 random_shuffle【洗牌:对指定范围的容器元素随机排序】

作用:对指定范围的容器元素随机排序,即洗牌

注1:使用random_shuffle算法时,需包含头文件include <algorithm>
注2:为保证随机性,需包含头文件include <ctime>,添加随机数种子srand((unsigned int)time(NULL));

函数原型
random_shuffle(iterator begin, iterator end);

参数解释
begin:迭代器起始位置;
end:迭代器结束位置;

示例

#include <iostream>
using namespace std;

#include <vector>
#include <algorithm>	//使用sort算法
#include <ctime>	//添加随机数种子

int main() {
	//添加随机数种子
	srand((unsigned int)time(NULL));

	vector<int> v;
	for (int i = 0; i < 10; i++) {
		v.push_back(i);
	}

	//0 1 2 3 4 5 6 7 8 9
	for_each(v.begin(), v.end(), [](int val) {cout << val << " "; });

	//洗牌算法
	random_shuffle(v.begin(), v.end());

	//随机排序:6 9 1 4 3 2 0 5 7 8
	for_each(v.begin(), v.end(), [](int val) {cout << val << " "; });

	return 0;
}

3.3 merge【合并两个容器的元素,并存储至新容器中】

作用合并两个容器的元素,并存储至新容器中。

注1:使用merge算法时,需包含头文件include <algorithm>
注2:使用merge算法时,两个源容器的元素必须有序且顺序一致合并后,新容器中的元素仍有序
注3:使用merge算法时,需为目标容器提前开辟内存空间,如dest.resize(src1.size() + src2.size());,否则程序运行时崩溃。

函数原型
merge(iterator begin1, iterator end1, iterator begin2, iterator end2, iterator dest);

参数解释
begin1:源容器1迭代器的起始位置;
end1:源容器1迭代器的结束位置;
begin2:源容器2迭代器的起始位置;
end2:源容器2迭代器的结束位置;
dest目标容器迭代器的起始位置。

示例

#include <iostream>
using namespace std;

#include <vector>
#include <algorithm>	//使用merge算法

int main() {
	//合并的两个源容器必须有序,且顺序一致
	vector<int> src1;
	for (int i = 0; i < 5; i++) {
		src1.push_back(i);
	}

	vector<int> src2;
	for (int i = 5; i < 10; i++) {
		src2.push_back(i);
	}

	//合并前,需为目标容器提前分配内存空间
	vector<int> dest;
	dest.resize(src1.size() + src2.size());

	//merge合并
	merge(src1.begin(), src1.end(), src2.begin(), src2.end(), dest.begin());
	//0 1 2 3 4 5 6 7 8 9
	for_each(dest.begin(), dest.end(), [](int val) {cout << val << " "; });

	return 0;
}

3.4 reverse【反转容器元素】

作用反转容器元素。

注:使用reverse算法时,需包含头文件include <algorithm>

函数原型
reverse(iterator begin, iterator end);

参数解释
begin:迭代器起始位置;
end:迭代器结束位置;

示例

#include <iostream>
using namespace std;

#include <vector>
#include <algorithm>	//使用reverse算法

int main() {
	vector<int> v;

	v.push_back(9);
	v.push_back(1);
	v.push_back(7);
	v.push_back(6);
	v.push_back(3);

	for_each(v.begin(), v.end(), [](int val) {cout << val << " "; });	//9 1 7 6 3

	//反转容器的元素
	reverse(v.begin(), v.end());

	for_each(v.begin(), v.end(), [](int val) {cout << val << " "; });	//3 6 7 1 9

	return 0;
}

4 常用拷贝【copy】和替换【replace、replace_if、swap】算法

算法简介
copy:拷贝容器元素至另一容器。
replace:将容器内的指定值全部替换为新值。
replace_if按条件将容器内指定范围的旧元素替换为新元素。
swap:互换两个相同类型容器的元素。


4.1 copy【拷贝容器元素至另一容器】

作用拷贝容器元素至另一容器。

注1:使用copy算法时,需包含头文件include <algorithm>
注2:使用copy算法时,需为目标容器提前开辟内存空间,如dest.resize(src.size());,否则程序运行时崩溃。

函数原型
copy(iterator begin, iterator end, iterator dest);

参数解释
begin:源容器迭代器的起始位置;
end:源容器迭代器的结束位置;
dest目标容器迭代器的起始位置。

注:实际开发时,copy算法应用较少,建议使用容器的赋值操作

示例

#include <iostream>
using namespace std;

#include <vector>
#include <algorithm>	//使用copy算法

int main() {
	vector<int> src;
	for (int i = 0; i < 5; i++) {
		src.push_back(i);
	}
	for_each(src.begin(), src.end(), [](int val) {cout << val << " "; });	//0 1 2 3 4

	//copy算法拷贝元素时,需为目标容器提前开辟内存空间
	vector<int> dest;
	dest.resize(src.size());

	//copy
	copy(src.begin(), src.end(), dest.begin());
	for_each(dest.begin(), dest.end(), [](int val) {cout << val << " "; });	//0 1 2 3 4

	return 0;
}

4.2 replace【将指定值全部替换为新值】

作用:将容器内的指定值的元素全部替换为新值。

注:使用replace算法时,需包含头文件include <algorithm>

函数原型
replace(iterator begin, iterator end, oldvalue, newvalue);

参数解释
begin:迭代器起始位置;
end:迭代器结束位置;
oldvalue:被替换的旧元素;
oldvalue:替换的新元素。

示例

#include <iostream>
using namespace std;

#include <vector>
#include <algorithm>	//使用replace算法

int main() {
	vector<int> v;

	v.push_back(9);
	v.push_back(7);
	v.push_back(1);
	v.push_back(7);
	v.push_back(6);
	v.push_back(7);
	v.push_back(3);

	for_each(v.begin(), v.end(), [](int val) {cout << val << " "; });	//9 7 1 7 6 7 3

	//replace():将容器内的指定值全部替换为新值
	replace(v.begin(), v.end(), 7, 0);
	for_each(v.begin(), v.end(), [](int val) {cout << val << " "; });	//9 0 1 0 6 0 3

	return 0;
}

4.3 replace_if【将满足指定条件的元素全部替换为新元素】

作用:将容器内满足指定条件的元素全部替换为新元素。

注:使用replace_if算法时,需包含头文件include <algorithm>

函数原型
replace_if(iterator begin, iterator end, _pred, newvalue);

参数解释
begin:迭代器起始位置;
end:迭代器结束位置;
_pred:指定条件。
①普通回调函数;
谓词(返回类型为bool的仿函数);
③匿名函数(lambda表达式)。
newvalue:替换的新元素。

示例

#include <iostream>
using namespace std;

#include <vector>
#include <algorithm>	//使用replace_if算法

//回调函数
bool lessThanFive(int val) {
	return val < 5;
}

//谓词(返回类型为bool的仿函数/函数对象)
class LessThanFive {
public:
	bool operator()(int val) {
		return val < 5;
	}
};

//将小于5的元素全部替换为100
int main() {
	vector<int> v;

	v.push_back(9);
	v.push_back(1);
	v.push_back(7);
	v.push_back(6);
	v.push_back(3);
	for_each(v.begin(), v.end(), [](int val) {cout << val << " "; });	//9 1 7 6 3

	//回调函数
	//replace_if(v.begin(), v.end(), lessThanFive, 100);
	//for_each(v.begin(), v.end(), [](int val) {cout << val << " "; });	//9 100 7 6 100

	//谓词
	//replace_if(v.begin(), v.end(), LessThanFive(), 100);
	//for_each(v.begin(), v.end(), [](int val) {cout << val << " "; });	//9 100 7 6 100

	//匿名函数(lambda表达式)
	replace_if(v.begin(), v.end(), [](int val) {return val < 5; }, 100);
	for_each(v.begin(), v.end(), [](int val) {cout << val << " "; });	//9 100 7 6 100

	return 0;
}

4.4 swap【互换两个同类型容器的元素】

作用:互换两个相同类型容器的元素。

注:使用swap算法时,需包含头文件include <algorithm>

函数原型
swap(container c1, container c2);

参数解释
c1:容器1;
c2:容器2。

示例

#include <iostream>
using namespace std;

#include <vector>
#include <algorithm>	//使用swap算法

int main() {
	vector<int> v1;
	vector<int> v2;

	for (int i = 0; i < 5; i++) {
		v1.push_back(i);
		v2.push_back(-i);
	}

	cout << "交换前..." << endl;
	for_each(v1.begin(), v1.end(), [](int val) {cout << val << " "; });	//0 1 2 3 4
	cout << endl;
	for_each(v2.begin(), v2.end(), [](int val) {cout << val << " "; });	//0 -1 -2 -3 -4
	cout << endl;

	//交换
	swap(v1, v2);

	cout << "交换后..." << endl;
	for_each(v1.begin(), v1.end(), [](int val) {cout << val << " "; });	//0 -1 -2 -3 -4
	cout << endl;
	for_each(v2.begin(), v2.end(), [](int val) {cout << val << " "; });	//0 1 2 3 4
	cout << endl;

	return 0;
}

5 常用算术生成算法【accumulate、fill】

算法简介
accumulate:计算容器指定区间内元素的累和
fill:向容器填充指定元素

注:算术生成算法属于小型算法,使用时需包含头文件#include <numeric>


5.1 accumulate【计算容器元素的累和】

作用:计算容器指定区间内元素的累和

注:使用accumulate算法时,需包含头文件include <numeric>

函数原型
accumulate(iterator begin, iterator end, value);

参数解释
begin:迭代器起始位置;
end:迭代器结束位置;
value起始累加值

示例

#include <iostream>
using namespace std;

#include <vector>
#include <numeric>		//使用accumulate算法
#include <algorithm>	//使用for_each算法

int main() {
	vector<int> v;

	v.push_back(9);
	v.push_back(1);
	v.push_back(7);
	v.push_back(6);
	v.push_back(3);

	//计算元素累和(起始累加值设置为0)
	int sum = accumulate(v.begin(), v.end(), 0);
	cout << "sum = " << sum << endl;	//26

	return 0;
}

5.2 fill【向容器填充指定元素】

作用:向容器填充指定元素

注:使用fill算法时,需包含头文件include <numeric>

函数原型
fill(iterator begin, iterator end, value);

参数解释
begin:迭代器起始位置;
end:迭代器结束位置;
value填充的指定值

示例

#include <iostream>
using namespace std;

#include <vector>
#include <numeric>		//使用fill算法
#include <algorithm>	//使用for_each算法

int main() {
	vector<int> v;
	v.resize(5);	//使用默认值0填充
	for_each(v.begin(), v.end(), [](int val) {cout << val << " "; });	//0 0 0 0 0

	//fill():向容器中填充指定元素
	fill(v.begin(), v.end(), 6);
	for_each(v.begin(), v.end(), [](int val) {cout << val << " "; });	//6 6 6 6 6
	
	return 0;
}

6 常用集合算法【set_intersection、set_union、set_difference】

算法简介
set_intersection:将两个容器的交集存储至新容器
set_union:将两个容器的并集存储至新容器
set_difference:将两个容器的差集存储至新容器


6.1 set_intersection【将两个容器的交集存储至新容器】

作用:将两个容器的交集存储至新容器,并返回交集中最后1个元素迭代器位置

注1:使用set_intersection算法时,需包含头文件include <algorithm>
注2:使用set_intersection算法时,需为目标容器提前开辟内存空间交集元素个数至多为两容器大小的较小值,如dest.resize( min(src1.size(), src2.size()) );,否则程序运行时崩溃。
注3:使用set_intersection算法时,两个源容器的元素必须有序且顺序一致,否则程序运行时崩溃。合并后,新容器中的元素仍有序
注4:遍历新容器时,迭代器结束位置需使用交集的最后1个元素的迭代器位置,而不能使用新容器的结束迭代器,否则可能出现多余的填充值0

函数原型
set_intersection(iterator begin1, iterator end1, iterator begin2, iterator end2, iterator dest);

参数解释
begin1:源容器1迭代器的起始位置;
end1:源容器1迭代器的结束位置;
begin2:源容器2迭代器的起始位置;
end2:源容器2迭代器的结束位置;
dest目标容器迭代器的起始位置。

示例

#include <iostream>
using namespace std;

#include <vector>
#include <algorithm>	//使用set_intersection算法

int main() {
	//合并的两个源容器必须有序,且顺序一致,否则程序运行时崩溃
	vector<int> src1;
	for (int i = 0; i < 5; i++) {
		src1.push_back(i);		//0 1 2 3 4
	}

	vector<int> src2;
	for (int i = 3; i < 8; i++) {
		src2.push_back(i);		//3 4 5 6 7
	}

	//合并前,需为目标容器提前分配内存空间
	vector<int> dest;
	//交集元素个数至多为两容器大小的较小值
	dest.resize(min(src1.size(), src2.size()));

	//求两容器元素的交集,返回交集最后1个元素的迭代器位置last
	vector<int>::iterator last = set_intersection(src1.begin(), src1.end(), src2.begin(), src2.end(), dest.begin());
	
	//遍历新容器时,迭代器结束位置需使用【交集】的最后1个元素的迭代器位置last
	for_each(dest.begin(), last, [](int val) {cout << val << " "; });			//3 4
	
	//不能使用新容器的结束迭代器dest.end(),否则可能出现多余的填充值0
	//dest容器大小为5个,交集元素共2个,多余3个填充0值
	//for_each(dest.begin(), dest.end(), [](int val) {cout << val << " "; });	//3 4 0 0 0 

	return 0;
}

6.2 set_union【将两个容器的并集存储至新容器】

作用:将两个容器的并集存储至新容器,并返回并集中最后1个元素迭代器位置

注1:使用set_union算法时,需包含头文件include <algorithm>
注2:使用set_union算法时,需为目标容器提前开辟内存空间并集元素个数至多为两容器大小的总和,如dest.resize(src1.size() + src2.size());,否则程序运行时崩溃。
注3:使用set_union算法时,两个源容器的元素必须有序且顺序一致,否则程序运行时崩溃。合并后,新容器中的元素仍有序
注4:遍历新容器时,迭代器结束位置需使用并集的最后1个元素的迭代器位置,而不能使用新容器的结束迭代器,否则可能出现多余的填充值0

函数原型
set_union(iterator begin1, iterator end1, iterator begin2, iterator end2, iterator dest);

参数解释
begin1:源容器1迭代器的起始位置;
end1:源容器1迭代器的结束位置;
begin2:源容器2迭代器的起始位置;
end2:源容器2迭代器的结束位置;
dest目标容器迭代器的起始位置。

示例

#include <iostream>
using namespace std;

#include <vector>
#include <algorithm>	//使用set_union算法

int main() {
	//合并的两个源容器必须有序,且顺序一致,否则程序运行时崩溃
	vector<int> src1;
	for (int i = 0; i < 5; i++) {
		src1.push_back(i);		//0 1 2 3 4
	}

	vector<int> src2;
	for (int i = 3; i < 8; i++) {
		src2.push_back(i);		//3 4 5 6 7
	}

	//合并前,需为目标容器提前分配内存空间
	vector<int> dest;
	//并集元素个数至多为两容器大小的总和
	dest.resize(src1.size() + src2.size());

	//求两容器元素的并集,返回并集最后1个元素的迭代器位置last
	vector<int>::iterator last = set_union(src1.begin(), src1.end(), src2.begin(), src2.end(), dest.begin());

	//遍历新容器时,迭代器结束位置需使用【并集】的最后1个元素的迭代器位置last
	for_each(dest.begin(), last, [](int val) {cout << val << " "; });			//0 1 2 3 4 5 6 7

	//不能使用新容器的结束迭代器dest.end(),否则可能出现多余的填充值0
	//dest容器大小为10个,并集元素共8个,多余2个填充0值
	//for_each(dest.begin(), dest.end(), [](int val) {cout << val << " "; });	//0 1 2 3 4 5 6 7 0 0

	return 0;
}

6.3 set_difference【将两个容器的差集存储至新容器】

作用:将两个容器的差集存储至新容器,并返回差集中最后1个元素迭代器位置

注1:使用set_difference算法时,需包含头文件include <algorithm>
注2:使用set_difference算法时,需为目标容器提前开辟内存空间差集元素个数至多为两容器大小的较大值,如dest.resize( max(src1.size(), src2.size()) );,否则程序运行时崩溃。
注3:使用set_difference算法时,两个源容器的元素必须有序且顺序一致,否则程序运行时崩溃。合并后,新容器中的元素仍有序
注4:遍历新容器时,迭代器结束位置需使用差集的最后1个元素的迭代器位置,而不能使用新容器的结束迭代器,否则可能出现多余的填充值0

函数原型
set_difference(iterator begin1, iterator end1, iterator begin2, iterator end2, iterator dest);

参数解释
begin1:源容器1迭代器的起始位置;
end1:源容器1迭代器的结束位置;
begin2:源容器2迭代器的起始位置;
end2:源容器2迭代器的结束位置;
dest目标容器迭代器的起始位置。

示例

#include <iostream>
using namespace std;

#include <vector>
#include <algorithm>	//使用set_difference算法

int main() {
	//合并的两个源容器必须有序,且顺序一致,否则程序运行时崩溃
	vector<int> src1;
	for (int i = 0; i < 5; i++) {
		src1.push_back(i);		//0 1 2 3 4
	}

	vector<int> src2;
	for (int i = 3; i < 8; i++) {
		src2.push_back(i);		//3 4 5 6 7
	}

	//合并前,需为目标容器提前分配内存空间
	vector<int> dest;
	//差集元素个数至多为两容器大小的较大值
	dest.resize(max(src1.size(), src2.size()));

	cout << "容器src1与容器src2的差集:" << endl;
	//求两容器元素的差集,返回差集最后1个元素的迭代器位置last
	vector<int>::iterator last = set_difference(src1.begin(), src1.end(), src2.begin(), src2.end(), dest.begin());

	//遍历新容器时,迭代器结束位置需使用【差集】的最后1个元素的迭代器位置last
	for_each(dest.begin(), last, [](int val) {cout << val << " "; });			//0 1 2
	cout << endl;

	//不能使用新容器的结束迭代器dest.end(),否则可能出现多余的填充值0
	//dest容器大小为5个,差集元素共3个,多余2个填充0值
	//for_each(dest.begin(), dest.end(), [](int val) {cout << val << " "; });	//0 1 2 0 0


	cout << "容器src2与容器src1的差集:" << endl;
	last = set_difference(src2.begin(), src2.end(), src1.begin(), src1.end(), dest.begin());
	//遍历新容器时,迭代器结束位置需使用【差集】的最后1个元素的迭代器位置last
	for_each(dest.begin(), last, [](int val) {cout << val << " "; });			//5 6 7
	cout << endl;

	//不能使用新容器的结束迭代器dest.end(),否则可能出现多余的填充值0
	//dest容器大小为5个,差集元素共3个,多余2个填充0值
	//for_each(dest.begin(), dest.end(), [](int val) {cout << val << " "; });	//5 6 7 0 0

	return 0;
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值