介绍
主要有头文件<algorithm> <functional> <numeric> , <algorithm> 是STL头文件最大的一个。 <numeric> 体积很小,只包括几个在序列上面进行简单数学运算的模板函数, <functional> 定义了一些模板类。
常用的遍历算法
for_each 和transform , 需包含 <algorithm> 头文件
for_each 遍历容器
- 函数原型:
for_each(iterator beg, iterator end, _func); ,func是函数或函数对象都可以 - 函数内部是for循环,遍历从起始迭代器,到结束迭代器,执行传入的函数或仿函数操作。
void print01(int val) {
cout << val << " ";
}
for_each(v.begin(), v.end(), print01);
class print02 {
public:
void operator()(int val) {
cout << val << " ";
}
};
for_each(v.begin(), v.end(), print02());
transform 搬运容器到另一个容器中
- 函数原型:
transform(iterator beg1, iterator end1, iterator beg2, _func); beg1是源容器开始迭代器,end1是源容器结束迭代器,beg2是目标容器开始迭代器 _func 函数或者函数对象,在从源容器搬运到目标容器进行的操作class TransForm{
public:
int operator()(int val){
return val;
}
};
vector<int>vTarget;
vTarget.resize(v.size());
transform(v.begin(), v.end(), vTarget.begin(), TransForm());
常用查找算法
find //查找元素 find_if //按条件查找元素 adjacent_find //查找相邻重复元素 binary_search //二分查找法 count //统计元素个数 -count_if //按条件统计元素个数
find 查找指定元素
- 函数原型:
find(iterator beg, iterator end, value); ,开始迭代器,结束迭代器和要查找的元素 - 找到返回指定元素的迭代器,找不到返回结束迭代器end()
- 查找内置数据类型
vector<int>::iterator it = find(v.begin(), v.end(), 5);
- find底层中是for循环,遍历从起始迭代器,到结束迭代器,判断迭代器指向的值是否 =传入的value。在查找自定义数据类型时,编译器不知道如何判断自定义类型的相等,因此需要重载==运算符。
class Person {
public:
Person(string name, int age) {
this->m_Name = name;
this->m_Age = age;
}
bool operator==(const Person& p){
if (this->m_Name == p.m_Name && this->m_Age == p.m_Age) {
return true;
}
return false;
}
string m_Name;
int m_Age;
};
void test02() {
vector<Person> v;
Person p1("aaa", 10);
Person p2("bbb", 20);
Person p3("ccc", 30);
Person p4("ddd", 40);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
vector<Person>::iterator it = find(v.begin(), v.end(), p2);
if (it == v.end())
{
cout << "没有找到!" << endl;
}
else
{
cout << "找到姓名:" << it->m_Name << " 年龄: " << it->m_Age << endl;
}
}
find_if 按条件查找元素
- 函数原型:
find_if(iterator beg, iterator end, _Pred); 第三个参数是一个谓词,可以按照自己的条件找容器中是否有指定的数据。 - 有则返回当前迭代器,没有返回end()
-
查找内置数据类型 class GreaterFive{
public:
bool operator()(int val){
return val > 5;
}
};
vector<int>::iterator it = find_if(v.begin(), v.end(), GreaterFive());
if (it == v.end()) {
cout << "没有找到!" << endl;
}
else {
cout << "找到大于5的数字:" << *it << endl;
}
-
查找自定义数据类型
class Person {
public:
Person(string name, int age){
this->m_Name = name;
this->m_Age = age;
}
public:
string m_Name;
int m_Age;
};
class Greater20
{
public:
bool operator()(Person &p){
return p.m_Age > 20;
}
};
void test02() {
vector<Person> v;
Person p1("aaa", 10);
Person p2("bbb", 20);
Person p3("ccc", 30);
Person p4("ddd", 40);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
vector<Person>::iterator it = find_if(v.begin(), v.end(), Greater20());
if (it == v.end()){
cout << "没有找到!" << endl;
}
else{
cout << "找到姓名:" << it->m_Name << " 年龄: " << it->m_Age << endl;
}
}
adjacent_find 查找相邻重复元素
binary_search 二分查找指定元素是否存在
count 统计元素个数
- 函数原型:
count(iterator beg, iterator end, value); - 返回值即为容器中value的个数,自定义数据类型需要重载==运算符。
- 统计内置数据类型
int num = count(v.begin(), v.end(), 4);
- 统计自定义数据类型
class Person{
public:
Person(string name, int age){
this->m_Name = name;
this->m_Age = age;
}
bool operator==(const Person & p){
if (this->m_Age == p.m_Age)
{
return true;
}
else
{
return false;
}
}
string m_Name;
int m_Age;
};
void test02(){
vector<Person> v;
Person p1("刘备", 35);
Person p2("关羽", 35);
Person p3("张飞", 35);
Person p4("赵云", 30);
Person p5("曹操", 25);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
v.push_back(p5);
Person p("诸葛亮",35);
int num = count(v.begin(), v.end(), p);
cout << "num = " << num << endl;
}
count_if 按条件统计元素个数
- 函数原型:
count_if(iterator beg, iterator end, _Pred); _Pred 谓词用来指定统计规则 - 自定义数据类型不需要重载,和正常的一样
- 统计内置数据类型
class Greater4{
public:
bool operator()(int val){
return val >= 4;
}
};
int num = count_if(v.begin(), v.end(), Greater4());
- 统计自定义数据类型
class AgeLess35{
public:
bool operator()(const Person &p){
return p.m_Age < 35;
}
};
int num = count_if(v.begin(), v.end(), AgeLess35());
常用排序算法
sort //对容器内元素进行排序 random_shuffle //洗牌 指定范围内的元素随机调整次序 merge // 容器元素合并,并存储到另一容器中 reverse // 反转指定范围的元素
sort 容器内元素进行排序
-
函数原型:sort(iterator beg, iterator end, _Pred); -
_Pred 谓词用来指定统计规则,默认为升序。 -
若要更改为降序,可以自己写函数或函数对象,也可以调用内建函数对象greater<int>() ,需包含头文件#include <functional>
sort(v.begin(), v.end());
sort(v.begin(), v.end(), greater<int>());
random_shuffle 指定范围内的元素随机调整次序
merge 两个容器元素合并,并存储到另一容器中
-
函数原型:merge(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest); dest是目标容器开始迭代器。 -
两个容器必须是有序的 ,合并之后也是有序的。 -
目标容器需要提前开辟空间
vector<int> vtarget;
vtarget.resize(v1.size() + v2.size());
merge(v1.begin(), v1.end(), v2.begin(), v2.end(), vtarget.begin());
reverse 容器内元素反转
常用拷贝和替换算法
copy // 容器内指定范围的元素拷贝到另一容器中 replace // 将容器内指定范围的旧元素修改为新元素 replace_if // 容器内指定范围满足条件的元素替换为新元素 swap // 互换两个容器的元素
copy 指定范围的元素拷贝到另一容器中
replace 指定范围的旧元素修改为新元素
- 函数原型:
replace(iterator beg, iterator end, oldvalue, newvalue); - 使用:
replace(v.begin(), v.end(), 20,2000);
replace_if 将区间内满足条件的元素,替换成指定元素
-
函数原型: replace_if(iterator beg, iterator end, _pred, newvalue); _pred 谓词指定条件
class ReplaceGreater30{
public:
bool operator()(int val){
return val >= 30;
}
};
replace_if(v.begin(), v.end(), ReplaceGreater30(), 3000);
swap 互换两个容器的元素
- 函数原型:
swap(container c1, container c2); ,两种容器需要同种类型。 - 使用:
swap(v1, v2);
常用算术生成算法
小型算法,需包含头文件#include <numeric> accumulate // 计算容器元素累计总和 fill // 向容器中添加元素
accumulate 容器元素累计总和
- 函数原型
accumulate(iterator beg, iterator end, value); value 指起始的累加值。 - 使用:
int total = accumulate(v.begin(), v.end(), 0);
fill 向容器中填充指定的元素
- 函数原型:
fill(iterator beg, iterator end, value); - 使用:
fill(v.begin(), v.end(), 100);
常用集合算法
set_intersection // 求两个容器的交集 set_union // 求两个容器的并集 set_difference // 求两个容器的差集
set_intersection 容器的交集
- 函数原型:
set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest); dest 为目标容器的起始迭代器,函数返回值为新容器的end()迭代器。- 两个集合必须为有序序列
- 目标容器需提前分配空间。大小为容器可能性中最大的。eg取交集,容器最大为一个容器完全包含了另一个容器。即小的容器的大小。
- 由于我们分配的容器空间可能偏大,因此需要使用目标容器返回的结束的迭代器。
vTarget.resize(min(v1.size(), v2.size()));
vector<int>::iterator itEnd =
set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
并集与差集同理
并集目标容器开辟空间需要两个容器相加 vTarget.resize(v1.size() + v2.size()); 差集目标容器开辟空间是两个容器中较大值 vTarget.resize( max(v1.size() , v2.size()));
|