C++ 提高篇 8 之 STL 常用算法一

STL 常用算法

概述

  1. 算法主要是由头文件 <algorithm> <functional> <numeric> 组成
  2. <algorithm> 是所有 STL 头文件中最大的一个,范围涉及到比较、交换、查找、遍历、复制、修改等
  3. <functional> 定义了一些模板类,用以声明函数对象
  4. <numeric> 体积很小,只包括几个在序列上面进行简单数学运算的模板函数

—— 常用遍历算法

算法简介

  1. for_each // 遍历容器
  2. transform // 搬运容器到另一个容器

for_each 算法

函数原型

for_each(iterator begin, iterator end, _func); 

如下利用 for_each 算法遍历存放在 vector 容器中的一组数据

#include <iostream>
using namespace std;
#include <vector> // 用于创建 vector 容器
#include <algorithm> // 用于 for_each 算法

void Print1(int value) {
	cout << value << " ";
}

class Print2 {
public:
	void operator()(int value) {
		cout << value << " ";
	}
};

int main() {

	// 1. 下面创建一个包含 10 个数据的 vector 容器
	vector<int> v;
	for (int i = 0; i < 10; i++) {
		v.push_back(i + 1);
	}

	// 2. 关于如何将 vector 数组容器中的元素输出,以下使用遍历算法
	// 第一个和第二个参数分别是迭代器指向的起始位置和结束位置
	// 第三个参数是仿函数,将遍历到的元素作为参数传入第三个参数代表的函数中

	// 普通函数
	for_each(v.begin(), v.end(), Print1); // 1 2 3 4 5 6 7 8 9 10
	cout << endl;

	// 仿函数
	for_each(v.begin(), v.end(), Print2()); // 1 2 3 4 5 6 7 8 9 10
	cout << endl;

	system("pause");
	return 0;
}

transform 算法

函数原型

transform(iterator begin1, iterator end1, iterator begin2, _func);

如下利用 transform 算法,将某容器中(或进行某种运算后的)的元素搬运到另一个容器

#include <iostream>
using namespace std;
#include <vector> // 用于创建 vector 容器
#include <algorithm> // 用于 transform 算法

class Print {
public:
	void operator()(int value) {
		cout << value << " ";
	}
};

class Transform1 {
public:
	int operator()(int value) {
		return value;
	}
};

class Transform2 {
public:
	int operator()(int value) {
		return value + 100;
	}
};

int main() {

	// 1. 下面创建一个包含 10 个数据的 vector 容器
	vector<int> v;
	for (int i = 0; i < 10; i++) {
		v.push_back(i + 1);
	}
	// 2. 创建目标容器 v1,如何将容器 v 中的数据搬运到另一个容器中呢?
	vector<int> v1;
	// 在使用搬运之前,需要将 v1 容器扩容,不然将导致程序崩溃
	v1.resize(v.size());
	// 此处我们使用 transfrom 算法
	transform(v.begin(), v.end(), v1.begin(), Transform1());

	// 3. 分别打印容器 v 和 v1
	for_each(v.begin(), v.end(), Print()); // 1 2 3 4 5 6 7 8 9 10
	cout << endl;
	for_each(v1.begin(), v1.end(), Print()); // 1 2 3 4 5 6 7 8 9 10
	cout << endl;

	// 4. 如果我们想要将前一个容器中的元素做某种运算后搬运到新的容器
	// 那么就需要修改 transform 的第四个参数 _func 函数的返回值
	vector<int> v2;
	v2.resize(v.size());
	transform(v.begin(), v.end(), v2.begin(), Transform2());
	for_each(v2.begin(), v2.end(), Print()); // 101 102 103 104 105 106 107 108 109 110
	cout << endl;

	system("pause");
	return 0;
}

—— 常用查找算法

算法简介

  1. find // 查找元素
  2. find_if // 按条件查找元素
  3. adjacent_find // 查找相邻重复元素
  4. binary_search // 二分查找法
  5. count // 统计元素的个数
  6. count_if // 按条件统计元素的个数

find 算法

功能描述

查找指定元素,找到返回该元素的迭代器,否则返回结束迭代器 end()

函数原型

find(iterator begin, iterator end, value);

如下利用 find 算法,查找内置数据类型

#include <iostream>
using namespace std;
#include <vector> // 用于创建 vector 容器
#include <algorithm> // 用于 for_each 和 find 算法

class Print {
public:
	void operator()(int value) {
		cout << value << " ";
	}
};

int main() {

	// 1. 下面创建一个包含 5 个数据的 vector 容器
	vector<int> v;
	for (int i = 0; i < 5; i++) {
		v.push_back(i + 1);
	}
	// 遍历容器中元素
	for_each(v.begin(), v.end(), Print()); // 1 2 3 4 5
	cout << endl;

	// 2. 查找容器中是否存在元素 5
	vector<int>::iterator pos = find(v.begin(), v.end(), 5);
	if (pos == v.end()) {
		cout << "没有找到该元素!" << endl;
	}
	else {
		cout << "找到该元素:" << *pos << endl; // 找到该元素:5
	}

	system("pause");
	return 0;
}

如下利用 find 算法,查找自定义数据类型

#include <iostream>
using namespace std;
#include <vector> // 用于创建 vector 容器
#include <algorithm> // 用于 for_each 和 find 算法
#include <string>

class Person {
public:
	Person(string name, int age) {
		this->Name_ = name;
		this->Age_ = age;
	}
	// 重载 == 运算符
	bool operator==(const Person &p) {
		if (this->Age_ == p.Age_) {
			return true;
		}
		else {
			return false;
		}
	}

	string Name_;
	int Age_;
};

class Print {
public:
	void operator()(const Person &p) {
		cout << "姓名:" << p.Name_ << " 年龄:" << p.Age_ << endl;
	}
};

void createPerson(vector<Person> &v) {
	string NameSeed = "ABCDE";
	for (int i = 0; i < 5; i++) {
		string name = "人员";
		name += NameSeed[i];
		int age = rand() % 30 + 30; // 30 ~ 69

		// 创建 Person
		Person p(name, age);
		// 将 p 存在 vector 数组中
		v.push_back(p);
	}
}

int main() {

	// 1. 下面创建一个包含 5 组数据的 vector 容器
	vector<Person> v;
	createPerson(v);

	// 打印 vector 容器中的人员
	cout << "随机生成的全部人员如下:" << endl;
	for_each(v.begin(), v.end(), Print());
	cout << "------------------------------" << endl;

	// 2. 在容器 v 中查找年龄和 p 相同的元素
	Person p("人员F", 40);
	vector<Person>::iterator pos = find(v.begin(), v.end(), p);
	if (pos != v.end()) {
		cout << "找到该人员,姓名为:" << pos->Name_ << " 年龄为:" << pos->Age_ << endl;
	}
	else {
		cout << "没有找到该人员" << endl;
	}
	// outputs:随机生成的全部人员如下:
	//		   姓名:人员A 年龄:41
	//		   姓名:人员B 年龄:47
	//		   姓名:人员C 年龄:34
	//		   姓名:人员D 年龄:40
	//		   姓名:人员E 年龄:59
	//		   ------------------------------
	//		   找到该人员,姓名为:人员D 年龄为:40
	
	system("pause");
	return 0;
}

find_if 算法

功能描述

按条件查找范围内元素,找到返回该元素的迭代器,否则返回结束迭代器 end()

函数原型

find_if(iterator begin, iterator end, _Pred);

如下利用 find_if 算法,查找内置数据类型

#include <iostream>
using namespace std;
#include <vector> // 用于创建 vector 容器
#include <algorithm> // 用于 for_each 和 find_if 算法

class Print {
public:
	void operator()(int value) {
		cout << value << " ";
	}
};

class greaterTwenty {
public:
	bool operator()(int value) {
		return value > 3;
	}
};

int main() {

	// 1. 下面创建一个包含 5 个数据的 vector 容器
	vector<int> v;
	for (int i = 0; i < 5; i++) {
		v.push_back(i + 1);
	}
	for_each(v.begin(), v.end(), Print()); // 1 2 3 4 5
	cout << endl;

	// 2. 查找容器中大于 3 的数据
	vector<int>::iterator pos = find_if(v.begin(), v.end(), greaterTwenty());
	if (pos != v.end()) {
		cout << "找到该元素:" << *pos << endl; // 找到该元素:4
	}
	else {
		cout << "没有找到该元素" << endl;
	}

	system("pause");
	return 0;
}

如下利用 find_if 算法,查找自定义数据类型

#include <iostream>
using namespace std;
#include <vector> // 用于创建 vector 容器
#include <algorithm> // 用于 for_each 和 find_if 算法
#include <string>

class Person {
public:
	Person(string name, int age) {
		this->Name_ = name;
		this->Age_ = age;
	}

	string Name_;
	int Age_;
};

class Print {
public:
	void operator()(const Person &p) {
		cout << "姓名:" << p.Name_ << " 年龄:" << p.Age_ << endl;
	}
};

void createPerson(vector<Person> &v) {
	string NameSeed = "ABCDE";
	for (int i = 0; i < 5; i++) {
		string name = "人员";
		name += NameSeed[i];
		int age = rand() % 30 + 30; // 30 ~ 69

		// 创建 Person
		Person p(name, age);
		// 将 p 存在 vector 数组中
		v.push_back(p);
	}
}

class greaterTwenty {
public:
	bool operator()(Person &p) {
		return p.Age_ > 40;
	}
};

int main() {

	// 1. 下面创建一个包含 5 组数据的 vector 容器
	vector<Person> v;
	createPerson(v);

	// 打印 vector 容器中的人员
	cout << "随机生成的全部人员如下:" << endl;
	for_each(v.begin(), v.end(), Print());
	cout << "------------------------------" << endl;

	// 2. 在容器 v 中查找年龄大于 p 的元素
	Person p("人员F", 40);
	// 第一个参数和第二个参数分别代表容器的起始迭代器和结束迭代器
	// 第三个参数是一个谓词
	vector<Person>::iterator pos = find_if(v.begin(), v.end(), greaterTwenty());

	if (pos != v.end()) {
		cout << "找到该人员,姓名为:" << pos->Name_ << " 年龄为:" << pos->Age_ << endl;
	}
	else {
		cout << "没有找到该人员" << endl;
	}
	// outputs:随机生成的全部人员如下:
	//		   姓名:人员A 年龄:41
	//		   姓名:人员B 年龄:47
	//		   姓名:人员C 年龄:34
	//		   姓名:人员D 年龄:40
	//		   姓名:人员E 年龄:59
	//		   ------------------------------
	//		   找到该人员,姓名为:人员A 年龄为:41
	
	system("pause");
	return 0;
}

adjacent_find 算法

功能描述

查找相邻重复元素,找到了返回相邻元素第一个位置的迭代器,否则返回 end()

函数原型

adjacent_find(iterator begin, iterator end);

如下利用 adjacent_find 算法,查找内置数据类型

#include <iostream>
using namespace std;
#include <vector> // 用于创建 vector 容器
#include <algorithm> // 用于 for_each 和 adjacent_find 算法

class Print {
public:
	void operator()(int value) {
		cout << value << " ";
	}
};

void Separate() {
	cout << "------------------------" << endl;
}

void func1() {
	// 1. 下面创建一个包含 5 个数据的 vector 容器 -- 存在相邻元素 3
	vector<int> v;
	v.push_back(1);
	v.push_back(5);
	v.push_back(2);
	v.push_back(3);
	v.push_back(3);
	for_each(v.begin(), v.end(), Print()); // 1 5 2 3 3
	cout << endl;

	// 2. 利用算法 adjacent_find 查找相邻元素并返回相邻元素第一个位置的迭代器
	vector<int>::iterator pos = adjacent_find(v.begin(), v.end());
	if (pos == v.end()) {
		cout << "案例1:没有查找到相邻元素!" << endl;
	}
	else {
		cout << "案例1:查找到相邻元素:" << *pos << endl;
	}
}

void func2() {
	// 1. 下面创建一个包含 5 个数据的 vector 容器 -- 不存在相邻元素
	vector<int> v;
	v.push_back(1);
	v.push_back(5);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	for_each(v.begin(), v.end(), Print()); // 1 5 2 3 4
	cout << endl;

	// 2. 利用算法 adjacent_find 查找相邻元素并返回相邻元素第一个位置的迭代器
	vector<int>::iterator pos = adjacent_find(v.begin(), v.end());
	if (pos == v.end()) {
		cout << "案例2:没有查找到相邻元素!" << endl;
	}
	else {
		cout << "案例2:查找到相邻元素:" << *pos << endl;
	}
}

int main() {

	func1();
	Separate();
	func2();
	// outpus:1 5 2 3 3
	//        案例1:查找到相邻元素:3
	//		  ------------------------
	//		  1 5 2 3 4
	//		  案例2:没有查找到相邻元素!

	system("pause");
	return 0;
}

binary_search 算法

功能描述

重点:容器中存放的必须是有序序列!

查找指定元素是否存在,找到了返回 true,否则返回 false

函数原型

bool binary_search(iterator begin, iterator end, value);

如下利用 binary_search 算法,查找内置数据类型

#include <iostream>
using namespace std;
#include <vector> // 用于创建 vector 容器
#include <algorithm> // 用于 for_each 和 binary_search 算法

class Print {
public:
	void operator()(int value) {
		cout << value << " ";
	}
};

void PrintVector(vector<int> &v) {
	for_each(v.begin(), v.end(), Print()); 
	cout << endl;
}

int main() {

	vector<int> v;
	for (int i = 0; i < 10; i++) {
		v.push_back(i);
	}
	PrintVector(v); // 0 1 2 3 4 5 6 7 8 9

	// 查找元素 9 是否存在
	bool exist = binary_search(v.begin(), v.end(), 9);
	cout << "输出 1:存在;2:不存在,输出结果为:" << exist << endl; // 输出 1:存在;2:不存在,输出结果为:1

	// 重点:使其成为一个不有序序列 -- 二分法将出错
	v.push_back(2);
	PrintVector(v); // 0 1 2 3 4 5 6 7 8 9 2
	exist = binary_search(v.begin(), v.end(), 9);
	cout << "输出 1:存在;2:不存在,输出结果为:" << exist << endl; // 输出 1:存在;2:不存在,输出结果为:0

	system("pause");
	return 0;
}

如下利用 binary_search 算法,查找自定义数据类型(如下代码报错)

#include <iostream>
using namespace std;
#include <vector> // 用于创建 vector 容器
#include <algorithm> // 用于 for_each 和 binary_search 算法
#include <string>

class Person {
public:
	Person(string name, int age) {
		this->Name_ = name;
		this->Age_ = age;
	}
	// 重载 == 运算符
	bool operator==(const Person &p) {
		return (this->Age_ == p.Age_);
	}

	string Name_;
	int Age_;
};

class Print {
public:
	void operator()(const Person &p) {
		cout << "姓名:" << p.Name_ << " 年龄:" << p.Age_ << endl;
	}
};

void PrintVector(vector<Person> &v) {
	for_each(v.begin(), v.end(), Print()); 
}

int main() {

	vector<Person> v;
	Person p1("人员A", 10);
	Person p2("人员B", 20);
	Person p3("人员C", 20);
	Person p4("人员D", 40);
	Person p5("人员E", 50);
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);
	v.push_back(p5);
	PrintVector(v);

	// 1. 查找年龄与 p 相同的元素是否存在
	Person p("人员F", 10);
	bool exist = binary_search(v.begin(), v.end(), p);
	cout << "输出 1:存在;2:不存在,输出结果为:" << exist << endl;

	system("pause");
	return 0;
}

count 算法

功能描述

统计元素个数

函数原型

count(iterator begin, iterator end, value);

如下利用 count 算法,统计内置数据类型

#include <iostream>
using namespace std;
#include <vector> // 用于创建 vector 容器
#include <algorithm> // 用于 for_each 和 count 算法

class Print {
public:
	void operator()(int value) {
		cout << value << " ";
	}
};

void PrintVector(vector<int> &v) {
	for_each(v.begin(), v.end(), Print());
	cout << endl;
}

int main() {

	vector<int> v;
	for (int i = 0; i < 10; i++) {
		v.push_back(i);
	}
	PrintVector(v); // 0 1 2 3 4 5 6 7 8 9

	// 1. 查找容器中 3 的个数
	cout << "元素 3 的个数:" << count(v.begin(), v.end(), 3) << endl; // 元素 3 的个数:1

	// 2. 查找容器中 100 的个数
	cout << "元素 100 的个数:" << count(v.begin(), v.end(), 100) << endl; // 元素 100 的个数:0

	system("pause");
	return 0;
}

如下利用 count 算法,统计自定义数据类型

#include <iostream>
using namespace std;
#include <vector> // 用于创建 vector 容器
#include <algorithm> // 用于 for_each 和 count 算法
#include <string>

class Person {
public:
	Person(string name, int age) {
		this->Name_ = name;
		this->Age_ = age;
	}
	// 重载 == 运算符
	bool operator==(const Person &p) {
		return (this->Age_ == p.Age_);
	}

	string Name_;
	int Age_;
};

class Print {
public:
	void operator()(const Person &p) {
		cout << "姓名:" << p.Name_ << " 年龄:" << p.Age_ << endl;
	}
};

void PrintVector(vector<Person> &v) {
	for_each(v.begin(), v.end(), Print()); 
}

int main() {

	vector<Person> v;
	Person p1("人员A", 10);
	Person p2("人员B", 20);
	Person p3("人员C", 20);
	Person p4("人员D", 40);
	Person p5("人员E", 50);
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);
	v.push_back(p5);
	PrintVector(v);
	
	// 1. 统计容器中年龄与 p 相等的个数
	Person p("人员F", 20);
	cout << "与 p 年龄相等的人数为:" << count(v.begin(), v.end(), p) << endl; // 与 p 年龄相等的人数为:2

	// 2. 统计容器中年龄与 p 相等的个数
	p.Age_ = 60;
	cout << "与 p 年龄相等的人数为:" << count(v.begin(), v.end(), p) << endl; // 与 p 年龄相等的人数为:0

	system("pause");
	return 0;
}

count_if 算法

功能描述

按条件统计元素个数

函数原型

count_if(iterator begin, iterator end, _Pred);

如下利用 count_if 算法,统计内置数据类型

#include <iostream>
using namespace std;
#include <vector> // 用于创建 vector 容器
#include <algorithm> // 用于 for_each 和 count_if 算法

class Print {
public:
	void operator()(int value) {
		cout << value << " ";
	}
};

void PrintVector(vector<int> &v) {
	for_each(v.begin(), v.end(), Print());
	cout << endl;
}

class greaterThree {
public:
	bool operator()(int value) {
		return value > 3;
	}
};

int main() {

	vector<int> v;
	for (int i = 0; i < 10; i++) {
		v.push_back(i);
	}
	PrintVector(v); // 0 1 2 3 4 5 6 7 8 9

	// 查找容器中大于元素 3 的个数
	cout << "大于元素 3 的个数:" << count_if(v.begin(), v.end(), greaterThree()) << endl; // 大于元素 3 的个数:6

	system("pause");
	return 0;
}

如下利用 count_if 算法,统计自定义数据类型

#include <iostream>
using namespace std;
#include <vector> // 用于创建 vector 容器
#include <algorithm> // 用于 for_each 和 count_if 算法
#include <string>

class Person {
public:
	Person(string name, int age) {
		this->Name_ = name;
		this->Age_ = age;
	}

	string Name_;
	int Age_;
};

class Print {
public:
	void operator()(const Person &p) {
		cout << "姓名:" << p.Name_ << " 年龄:" << p.Age_ << endl;
	}
};

void PrintVector(vector<Person> &v) {
	for_each(v.begin(), v.end(), Print());
}

class greaterTwenty {
public:
	bool operator()(const Person &p) {
		return p.Age_ > 20;
	}
};

int main() {

	vector<Person> v;
	Person p1("人员A", 10);
	Person p2("人员B", 20);
	Person p3("人员C", 20);
	Person p4("人员D", 40);
	Person p5("人员E", 50);
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);
	v.push_back(p5);
	PrintVector(v);

	// 统计容器中年龄大于 20 的个数
	cout << "年龄大于 20 的人数为:" << count_if(v.begin(), v.end(), greaterTwenty()) << endl; // 年龄大于 20 的人数为:2

	system("pause");
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

是我来晚了!

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

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

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

打赏作者

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

抵扣说明:

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

余额充值