C++ 自学
STL 常用算法
概述
- 算法主要是由头文件
<algorithm>
<functional>
<numeric>
组成 <algorithm>
是所有 STL 头文件中最大的一个,范围涉及到比较、交换、查找、遍历、复制、修改等<functional>
定义了一些模板类,用以声明函数对象<numeric>
体积很小,只包括几个在序列上面进行简单数学运算的模板函数
—— 常用遍历算法
算法简介
for_each
// 遍历容器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;
}
—— 常用查找算法
算法简介
find
// 查找元素find_if
// 按条件查找元素adjacent_find
// 查找相邻重复元素binary_search
// 二分查找法count
// 统计元素的个数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;
}