STL算法主要由头文件alpgorithm,functional和numeric组成。Algothrim是所有STL头文件中最大的一个,范围涉及到比较、交换、查找、遍历、复制和修改等。Numeric体积很小,只包括在几个序列上进行简单数学运算的模板函数。Functional定义了一些模板类,用以声明函数对象。
1、遍历算法
for_each | 遍历容器(熟练掌握) |
transform | 搬运容器到另一个容器中 |
case 1: for_each
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
void Print(int v)
{
cout << v << " ";
}
class Print2
{
public:
void operator()(int val)
{
cout << val << " ";
}
};
void test01()
{
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
//利用普通函数实现遍历操作
for_each(v1.begin(), v1.end(), Print);
//仿函数进行操作
for_each(v1.begin(), v1.end(), Print2());
}
int main()
{
test01();
}
case 2:tansform
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class Transform
{
public:
int operator()(int v)
{
return v+100; //在搬运过程中可以进行一些运算
}
};
class Print
{
public:
void operator()(int val)
{
cout << val << " ";
}
};
void test01()
{
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
vector<int> vTarget;
vTarget.resize(v1.size()); //目标容器需要提前开辟好空间
transform(v1.begin(),v1.end(),vTarget.begin(),Transform());
for_each(vTarget.begin(), vTarget.end(), Print());
cout << endl;
}
int main()
{
test01();
}
2、查找算法
Find | 查找元素 |
Find_if | 按条件查找元素 |
Adjacent_find | 查找相邻重复元素 |
Binary_search | 二分查找 |
Count | 统计元素个数 |
Count_if | 按条件统计元素个数 |
2.1、find
查找指定元素,找到返回指定元素的迭代器,找不到则返回结束迭代器end()。
Find(iterator beg, iterator end, value);
//beg 开始迭代器
//end 结束迭代器
//value 查找的元素
利用find可以在容器中找到指定元素,返回值是迭代器。
case 1:查找内置数据类型(查找等于5的数)
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
void test01()
{
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
vector<int>::iterator it=find(v1.begin(), v1.end(), 5);
if (it == v1.end())
{
cout << "没有找到!" << endl;
}
else
{
cout << "找到了"<<*it << endl;
}
}
int main()
{
test01();
}
case 2:查找自定义数据类型
#include<iostream>
#include<vector>
#include<algorithm>
#include"string"
using namespace std;
class Person
{
public:
Person(string name, int age)
{
this->m_name = name;
this->m_age = age;
}
//重载==,让底层find知道如何对比person数据类型
bool operator== (const Person& p)
{
if (this->m_name == p.m_name && this->m_age == p.m_age)
{
return true;
}
else
return false;
}
string m_name;
int m_age;
};
void test01()
{
vector<Person> v;
Person p1("wxq",10);
Person p2("szw", 20);
Person p3("czt", 30);
Person p4("dj", 40);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
//查找
Person pp("szw", 20);
vector<Person>::iterator it=find(v.begin(), v.end(), pp);
if (it == v.end())
{
cout << "没有找到!" << endl;
}
else
{
cout << "找到了" << (*it).m_name << ", age is " << (*it).m_age << endl;
}
}
int main()
{
test01();
}
2.1、find_if
按条件查找元素。
Find_if(iterator beg, iterator end, _Pred);
//按谓词查找,返回指定位置的迭代器,找不到则返回结束迭代器。
//beg 开始迭代器
//end 结束迭代器
//_Pred 函数或谓词(返回bool类型的仿函数)
case 1:查找内置数据类型
#include<iostream>
#include<vector>
#include<algorithm>
#include"string"
using namespace std;
class Greater
{
public:
bool operator()(int val)
{
return val > 5;
}
};
void test01()
{
vector<int> v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
vector<int>::iterator it =find_if(v.begin(),v.end(),Greater());
if (it == v.end())
{
cout << "没有找到!" << endl;
}
else
{
cout << "找到了大于5的数字为" << *it << endl;
}
}
int main()
{
test01();
}
case 2:查找自定义数据类型
#include<iostream>
#include<vector>
#include<algorithm>
#include"string"
using namespace std;
class Person
{
public:
Person(string name, int age)
{
this->m_name = name;
this->m_age = age;
}
string m_name;
int m_age;
};
class Greater20
{
public:
bool operator()(Person& p)
{
return p.m_age > 20;
}
};
void test01()
{
vector<Person> v;
Person p1("wxq", 10);
Person p2("szw", 20);
Person p3("czt", 30);
Person p4("dj", 40);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
//查找年龄大于20的人
vector<Person>::iterator it =find_if(v.begin(),v.end(),Greater20());
if (it == v.end())
{
cout << "没有找到!" << endl;
}
else
{
cout << "找到了大于20的人为:" << (*it).m_name << endl;
}
}
int main()
{
test01();
}
2.3、adjacent_find
查找相邻重复元素,返回相邻元素的第一个位置的迭代器。
Adjacent_find(iterator beg, iterator end);
#include<iostream>
#include<vector>
#include<algorithm>
#include"string"
using namespace std;
void test01()
{
vector<int> v;
v.push_back(0);
v.push_back(2);
v.push_back(0);
v.push_back(1);
v.push_back(1);
v.push_back(3);
vector<int>::iterator pos=adjacent_find(v.begin(), v.end());
if (pos == v.end())
{
cout << "未找到重复元素!" << endl;
}
else
{
cout << *pos << "重复!" << endl;
}
}
int main()
{
test01();
}
2.4、binary_search
Bool binary_search(iterator beg, iterator end, value);
//二分查找无法查找无序序列,且仅能返回true或false。
容器必须是有序序列。如果是无序的序列,则结果是未知的。
#include<iostream>
#include<vector>
#include<algorithm>
#include"string"
using namespace std;
void test01()
{
vector<int> v;
v.push_back(0);
v.push_back(1);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v.push_back(6);
bool result = binary_search(v.begin(), v.end(), 5);
if (!result)
{
cout << "未找到重复元素!" << endl;
}
else
{
cout << "找到了元素!" << endl;
}
}
int main()
{
test01();
}
2.5、count
统计元素个数,返回一个int类型。对于自定义数据类型,需要重载==号。
Count(iterator beg, iterator end, value);
case 1:统计内置数据类型
#include<iostream>
#include<vector>
#include<algorithm>
#include"string"
using namespace std;
void test01()
{
vector<int> v;
v.push_back(10);
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
v.push_back(40);
int num = count(v.begin(), v.end(), 40);
cout << num;
}
int main()
{
test01();
}
case 2:统计自定义数据类型
#include<iostream>
#include<vector>
#include<algorithm>
#include"string"
using namespace std;
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 test01()
{
vector<Person> v;
Person p1("wxq", 10);
Person p2("szw", 20);
Person p3("czt", 30);
Person p4("dj", 20);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
Person pp("xl", 20); //查找和XL相同岁数的人有几个
int num = count(v.begin(), v.end(), pp);
cout << "相同岁数的人有" << num << "个。" << endl;
}
int main()
{
test01();
}
2.6、count_if
按照条件统计元素个数。条件由谓词决定。谓词通过仿函数设置。
Count_if(iterator beg, iterator end, _Pred);
case 1:内置数据类型
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class Greater20
{
public:
bool operator()(int v)
{
return v > 20;
}
};
void test01()
{
vector<int> v;
v.push_back(10);
v.push_back(40);
v.push_back(30);
v.push_back(20);
v.push_back(40);
v.push_back(20);
int num=count_if(v.begin(), v.end(),Greater20());
cout << "大于20的元素个数为:" << num << endl;
}
int main()
{
test01();
}
case 2:自定义数据类型
#include<iostream>
#include<vector>
#include<algorithm>
#include"string"
using namespace std;
class Person
{
public:
Person(string name, int age)
{
this->m_name = name;
this->m_age = age;
}
string m_name;
int m_age;
};
class Greater20
{
public:
bool operator()(const Person& p)
{
return p.m_age > 20;
}
};
void test01()
{
vector<Person> v;
Person p1("wxq", 10);
Person p2("szw", 20);
Person p3("czt", 30);
Person p4("dj", 20);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
int num = count_if(v.begin(), v.end(), Greater20());
cout << "大于20岁的人数为" << num << "个。" << endl;
}
int main()
{
test01();
}
2.7、sort、random_shuffle、merge和reverse
Sort | 对容器内元素进行排序 |
Random_shuffle | 指定范围内元素随机调整次序(洗牌) |
Merge | 容器元素合并,并存储到另一容器中 |
reverse | 反转指定范围的元素 |
Sort(iterator beg, iterator end, _Pred);
//_Pred谓词,改变排序规则
Random_shuffle(iterator beg, iterator end);
Merge(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
//合并算法(两个容器必须有序(同为升序或降序),合并之后依然有序,合并后不会消除相同元素)
//dest目标容器的开始迭代器
Reverse(interator beg, iterator end);
case 1:排序算法
#include<iostream>
#include<vector>
#include<algorithm>
#include<functional>
using namespace std;
void Print(int val)
{
cout << val << " ";
}
void test01()
{
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(5);
v.push_back(1);
sort(v.begin(), v.end());
for_each(v.begin(), v.end(), Print);
cout << endl;
//降序排列
sort(v.begin(),v.end(),greater<int>());
for_each(v.begin(), v.end(), Print);
cout << endl;
}
int main()
{
test01();
}
case 2:洗牌算法
#include<iostream>
#include<vector>
#include<algorithm>
#include<time.h>
using namespace std;
void Print(int val)
{
cout << val << " ";
}
void test01()
{
srand((unsigned int)time(NULL)); //用系统时间生成种子作为真正的随机数
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(5);
v.push_back(3);
//升序排列
sort(v.begin(), v.end());
for_each(v.begin(), v.end(), Print);
cout << endl;
//洗牌1次
random_shuffle(v.begin(),v.end());
for_each(v.begin(), v.end(), Print);
cout << endl;
//洗牌2次
random_shuffle(v.begin(), v.end());
for_each(v.begin(), v.end(), Print);
cout << endl;
}
int main()
{
test01();
}
case 3:合并算法(两个容器必须有序,合并之后依然有序)
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
void Print(int val)
{
cout << val << " ";
}
void test01()
{
vector<int> v1;
vector<int> v2;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
v2.push_back(i + 1);
}
//目标容器,需要提前分配内存
vector<int> Target;
Target.resize(v1.size() + v2.size());
merge(v1.begin(), v1.end(), v2.begin(), v2.end(), Target.begin());
for_each(Target.begin(), Target.end(), Print);
cout << endl;
}
int main()
{
test01();
}
case 4:反转算法
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
void Print(int val)
{
cout << val << " ";
}
void test01()
{
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
for_each(v1.begin(), v1.end(), Print);
cout << endl;
//反转后的代码
reverse(v1.begin(), v1.end());
for_each(v1.begin(), v1.end(), Print);
cout << endl;
}
int main()
{
test01();
}
3、拷贝和替换算法
Copy | 容器内指定范围的元素拷贝到另一容器中 |
Replace | 将容器内指定范围内的元素修改为新元素 |
Replace_if | 容器内指定范围内满足条件的元素替换为新元素 |
swap | 互换两个容器的元素 |
Copy(iterator beg, iterator end, iterator dest);
//dest目标起始迭代器
replace(iterator beg, iterator end,oldvalue, newvalue);
//将旧值替换为新值
//注意是将其中元素均为oldvalue的值替换为newvalue
Replace_if(iterator beg, iterator end, _Pred, newvalue);
//_Pred谓词,即条件
Swap(container c1, container c2);
//同种类型的容器才可以互换
case 1:copy算法
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
void Print(int val)
{
cout << val << " ";
}
void test01()
{
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
vector<int> v2;
v2.resize(v1.size());//分配内存空间
copy(v1.begin(),v1.end(),v2.begin());
for_each(v2.begin(), v2.end(), Print);
cout << endl;
}
int main()
{
test01();
}
case 2:replace算法
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class MyPrint
{
public:
void operator()(int val)
{
cout << val << " ";
}
};
void test01()
{
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
cout << "替换前为:" << endl;
for_each(v1.begin(), v1.end(), MyPrint());
cout << endl;
replace(v1.begin(), v1.end(), 5, 50);
cout << "5替换为50:" << endl;
for_each(v1.begin(), v1.end(), MyPrint());
cout << endl;
}
int main()
{
test01();
}
case 3:replace_if算法
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class MyPrint
{
public:
void operator()(int val)
{
cout << val << " ";
}
};
class Greater5
{
public:
bool operator()(int val)
{
return val > 5;
}
};
void test01()
{
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
cout << "替换前为:" << endl;
for_each(v1.begin(), v1.end(), MyPrint()); //使用仿函数打印
cout << endl;
//将大于5的替换为9
replace_if(v1.begin(), v1.end(), Greater5(), 9);
cout << "替换前后:" << endl;
for_each(v1.begin(), v1.end(), MyPrint()); //使用仿函数打印
cout << endl;
}
int main()
{
test01();
}
case 4:swap算法
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class MyPrint
{
public:
void operator()(int val)
{
cout << val << " ";
}
};
void test01()
{
vector<int> v1;
vector<int> v2;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
v2.push_back(i+100);
}
cout << "交换前为:" << endl;
for_each(v1.begin(), v1.end(), MyPrint()); //使用仿函数打印
cout << endl;
for_each(v2.begin(), v2.end(), MyPrint());
cout << endl;
//交换v1和v2
swap(v1, v2);
cout << "交换后为:" << endl;
for_each(v1.begin(), v1.end(), MyPrint());
cout << endl;
for_each(v2.begin(), v2.end(), MyPrint());
cout << endl;
}
int main()
{
test01();
}
4、算术生成算法
算术生成算法属于小型算法,使用时需要包含头文件#include<numeric>
Accumulate | 计算容器元素累计总和 |
Fill | 向容器中添加元素 |
Accumulate(iterator beg, iterator end, value)
//value起始值,是一个起始的累加值
fill(iterator beg, iterator end, value);
//一般用于后期,重新填充
case 1:累加求和
#include<iostream>
#include<vector>
#include<numeric>
using namespace std;
void test01()
{
vector<int> v;
for (int i = 0; i <= 100; i++)
{
v.push_back(i);
}
int total=accumulate(v.begin(), v.end(), 0);//0表示起始累加值为0
cout << "total=" << total << endl;
}
int main()
{
test01();
}
case 2:填充算法
#include<iostream>
#include<vector>
#include<numeric>
#include<algorithm>
using namespace std;
void Print(int val)
{
cout << val << " ";
}
void test01()
{
vector<int> v;
v.resize(10);
//重新填充
fill(v.begin(), v.end(), 100);
for_each(v.begin(), v.end(), Print);
cout << endl;
}
int main()
{
test01();
}
5、集合算法
Set_intersection | 求两个容器的交集 |
Set_union | 求两个容器的并集 |
Set_difference | 求两个容器的差集 |
Set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
//会返回一个迭代器,指向交集最后位置
//dest目标容器的开始迭代器
//原容器必须为有序序列
Set_union(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
//dest目标容器的开始迭代器
//原容器必须为有序序列
//会返回一个迭代器,指向交集最后位置
case 1:求交集
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
void Print(int val)
{
cout << val << " ";
}
void test01()
{
vector<int> v1;
vector<int> v2;
vector<int> Target;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
v2.push_back(i + 5);
}
//目标容器需要提前开辟空间
//最特殊的情况为:大容器包含小容器,取小容器的空间即可
Target.resize(min(v1.size(),v2.size()));
vector<int>::iterator itEnd = set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), Target.begin());
for_each(Target.begin(), itEnd, Print); //开辟的容量可能会大,所以用返回的结束迭代器
cout << endl;
}
int main()
{
test01();
}
case 2:求并集
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
void Print(int val)
{
cout << val << " ";
}
void test01()
{
vector<int> v1;
vector<int> v2;
vector<int> Target;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
v2.push_back(i + 5);
}
//目标容器需要提前开辟空间
//最特殊的情况为:两个容器空间之和
Target.resize(v1.size()+v2.size());
vector<int>::iterator itEnd = set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), Target.begin());
for_each(Target.begin(), itEnd, Print); //开辟的容量可能会大,所以用返回的结束迭代器
cout << endl;
}
int main()
{
test01();
}