触类旁通
常用遍历算法
for_each
功能描述:实现遍历容器函数原型:for_each(iterator beg, iterator end, _func) ;// 遍历算法 遍历容器元素// beg 开始迭代器// end 结束迭代器// _func 函数或者函数对象
#include <iostream>
#include<vector>
#include<algorithm>//算法
using namespace std;
//常用遍历算法 for_each
//普通函数
void print01(int val){
cout<<val<<" ";
}
//仿函数
class print02{
public:
void operator()(int val){
cout<<val<<" ";
}
};
void test01(){
vector<int>v;
for(int i=0;i<10;i++){
v.push_back(i);
}
for_each(v.begin(),v.end(),print01);//始 末 函数名称 [这里传递的是函数指针(放函数名),不是仿函数,所以不加括号]
//创建仿函数因为重载了(),所以要加()
cout<<endl;
for_each(v.begin(),v.end(),print02());//函数对象
cout<<endl;
}
int main()
{
test01();
system("pause");
}
这里分别用两种函数类型实现,一种叫普通函数,也叫函数名 第二种叫仿函数,也叫函数对象
for_each(v.begin(),v.end(),print01);//始 末 函数名称 [这里传递的是函数指针(放函数名),不是仿函数,所以不加括号]
//创建仿函数因为重载了(),所以要加()
注意看括号添加有无
transform
功能描述:搬运容器到另一个容器中函数原型:transform(iterator beg1, iterator end1, iterator beg2, _func) ;//beg1 源容器开始迭代器//end1 源容器结束迭代器//beg2 目标容器开始迭代器//_func 函数或者函数对象
#include <iostream>
#include<vector>
#include<algorithm>//算法
using namespace std;
class Transform//搬运作用
{
public:
int operator()(int v){
return v+100;//搬运过程可以修改
}
};
class MyPrint{
public:
void operator()(int val){
cout<<val<<" ";
}
};
void test01(){
vector<int>v;
for(int i=0;i<10;i++){
v.push_back(i);
}
vector<int>vTarget;//目标容器
vTarget.resize(v.size());//目标容器 需要提前的开辟空间
//搬运的目标容器必须要提前开辟空间,否则无法正常搬运
transform(v.begin(),v.end(),vTarget.begin(),Transform());//仿函数
for_each(vTarget.begin(),vTarget.end(),MyPrint());
cout<<endl;
}
int main()
{
test01();
system("pause");
}
这个案例好,综合了foreach和transform算法
与第一个for_each相同,既可以用仿函数又可以用普通函数
vector<int>vTarget;//目标容器
vTarget.resize(v.size());//目标容器 需要提前的开辟空间
//搬运的目标容器必须要提前开辟空间,否则无法正常搬运这一块是核心,要有搬向空间和必须提前开辟空间
常用查找算法
find
功能描述:查找指定元素,找到返回指定元素的迭代器,找不到返回结束迭代器 end()函数原型:find(iterator beg, iterator end, value) ;// 按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置// beg 开始迭代器// end 结束迭代器// value 查找的元素
#include <iostream>
#include<vector>
#include<algorithm>//算法
#include<string>
using namespace std;
//查找 内置数据类型
void test01(){
vector<int> v;
for(int i=0;i<10;i++){
v.push_back(i);
}
//查找容器中是否有5这个元素
vector<int>::iterator it=find(v.begin(),v.end(),5);
if(it==v.end()){
cout<<"没有找到"<<endl;
}else{
cout<<"找到了"<<*it<<endl;
}
}
//查找自定义数据类型
class Person{
public:
Person(string name,int age)//构造函数赋初值
{
this->m_Name=name;
this->m_Age=age;
}
//自定义类型要重载 "==" 底层find知道如何对比person数据类型
bool operator==(const Person&p)//明确该如何对待Person数据类型 如何相等
{
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 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);
Person pp("bbb",20);//找个容器中看是否有一样的人
vector<Person>::iterator it=find(v.begin(),v.end(),pp);//查找p2
if(it==v.end()) {
cout<<"没找到"<<endl;
}else{
cout<<"找到了 姓名:"<<it->m_Name<<"年龄"<<it->m_Age<<endl;
}
}
int main()
{
// test01();
test02();
system("pause");
}
本代码数据类型用了一个内置数据类型,一个自定义
自定义类型要重载 "==" 底层find知道如何对比person数据类型
因为自定义类型不同于内置类型,用本代码为例,数据类型为Person p1("aaa",10);
以下是明确类型
bool operator==(const Person&p)//明确该如何对待Person数据类型 如何相等
{
if(this->m_Name==p.m_Name&&this->m_Age==p.m_Age){
return true;
}else{
return false;
}
}
find_if
功能描述:按条件查找元素函数原型:find_if(iterator beg, iterator end, _Pred) ;// 按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置// beg 开始迭代器// end 结束迭代器// _Pred 函数或者谓词(返回bool类型的仿函数)这个是主要的
![](https://img-blog.csdnimg.cn/direct/9ad29cb7b107417ab64494abdc472781.png)
加上了void print01(int val){
cout<<val<<" ";
}和for_each(v.begin()=it,v.end(),print01);
程序正常输出成功。所以要多思考,暂停一下也行.
#include <iostream>
#include<vector>
#include<algorithm>//算法
using namespace std;
void print01(int val){
cout<<val<<" ";
}
//1 查找内置数据类型
class GreaterFive{
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(),GreaterFive());
if(it==v.end()){
cout<<"没有找到"<<endl;
}
else{
cout<<"找到了大于5的数字为"<<*it<<endl;
}
for_each(v.begin()=it,v.end(),print01);
}
//2 查找自定义数据类型
void test02(){
}
int main()
{
test01();
system("pause");
}
是我预期的效果 ok
然后将其修改为自定义数据类型
#include <iostream>
#include<vector>
#include<algorithm>//算法
#include<string>
using namespace std;
//2 查找自定义数据类型
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 print02(Person val){
// cout<<val.m_Age<<val.m_Name<<" "<<endl;
//
//}
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);
//找年龄大于20的人
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;
}
// for_each(v.begin()=it,v.end(),print02);
}
int main()
{
// test01();
test02();
system("pause");
}
然后我想是不是也可以在这也加几行代码,实现效果和上一个相同,都可输出多个结果
经过了多次实验和思考,最后得出了代码
#include <iostream>
#include<vector>
#include<algorithm>//算法
#include<string>
using namespace std;
//2 查找自定义数据类型
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 print02(Person val){
cout<<val.m_Age<<val.m_Name<<" "<<endl;
}
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);
//找年龄大于20的人
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;
}
for_each(v.begin()=it,v.end(),print02);
}
int main()
{
// test01();
test02();
system("pause");
}
adjacent_find
功能描述:查找相邻重复元素 stl面试会用函数原型:adjacent_find(iterator beg, iterator end) ;// 查找 相邻重复元素 , 返回相邻元素的第一个位置的迭代器// beg 开始迭代器// end 结束迭代器
vector<int>::iterator pos=adjacent_find(v.begin(),v.end());//返回迭代器的位置
特点,其每个算法基本都返回迭代器了
代码如下
#include <iostream>
#include<vector>
#include<algorithm>//算法
//相邻且重复才满足
using namespace std;
void test01(){
vector<int>v;
v.push_back(0);
v.push_back(2);
v.push_back(0);
v.push_back(3);
v.push_back(1);
v.push_back(4);
v.push_back(3);
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();
system("pause");
}
binary_search
这个就和上面的有所不同了,上面的是查到了返回迭代器,查不到也返回迭代器。但binary_search返回的是真或假,是bool类型,告诉这个元素是否存在
//查找容器中是否有9元素
bool ret= binary_search(v.begin(),v.end(),9);返回是bool类型
功能描述:查找指定元素是否存在函数原型:bool binary_search(iterator beg, iterator end, value) ;// 查找指定的元素,查到 返回 true 否则 false// 注意 : 在无序序列中不可用// beg 开始迭代器// end 结束迭代器// value 查找的元素
#include <iostream>
#include<vector>
#include<algorithm>//算法
using namespace std;
void test01(){
vector<int>v;
for(int i=0;i<10;i++){
v.push_back(i);
}
//查找容器中是否有9元素
bool ret= binary_search(v.begin(),v.end(),9);
if(ret){
cout<<"找到了元素"<<endl;
}
else{
cout<<"未找到"<<endl;
}
}
int main()
{
test01();
system("pause");
}
count
功能描述:统计元素个数函数原型:count(iterator beg, iterator end, value) ;// 统计元素出现次数// beg 开始迭代器// end 结束迭代器// value 统计的元素
统计内置的数据类型
#include <iostream>
#include<vector>
#include<algorithm>//算法 头文件
using namespace std;
//1.统计内置数据类型
void test01(){
vector<int>v;
v.push_back(10);
v.push_back(20);
v.push_back(40);
v.push_back(30);
v.push_back(20);
v.push_back(40);
int num=count(v.begin(),v.end(),40);
cout<<"40的元素个数为:"<<num<<endl;
}
int main()
{
test01();
system("pause");
}
统计自定义数据类型
#include <iostream>
#include<vector>
#include<algorithm>//算法 头文件
#include<string>
using namespace std;
//2统计自定义数据类型
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("曹操",40);
//将人员插入在容器中
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<<endl;
}
int main()
{
// test01();
test02();
system("pause");
}
count_if
功能描述:按条件统计元素个数函数原型:count_if(iterator beg, iterator end, _Pred) ;// 按条件统计元素出现次数// beg 开始迭代器// end 结束迭代器// _Pred 谓词 很多算法使用函数对象来指定要进行的二元运算,或者指定谓词来确定进行特定运算。谓词是一个返回bool类型的值的函数,因为函数对象是一种类型的对象,实现operator()()成员函数并返回bool类型的值,所以函数对象也是谓词。谓词(返回bool类型的仿函数)经过代码验证发现谓词不止用仿函数(函数对象)来定义,用普通函数类型定义就行,主要是返回bool类型
内置数据类型
#include <iostream>
#include<vector>
#include<algorithm>//算法 头文件
using namespace std;
//统计内置数据类型
class Greater20//仿函数
{
public:
bool operator()(int val){
return val>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());//谓词
// 很多算法使用函数对象来指定要进行的二元运算,或者指定谓词来确定进行特定运算。谓词是一个返回bool类型的值的函数,
// 因为函数对象是一种类型的对象,实现operator()()成员函数并返回bool类型的值,所以函数对象也是谓词。
cout<<"大于20的元素个数为"<<num<<endl;
}
int main()
{
test01();
system("pause");
}
自定义数据类型
#include <iostream>
#include<vector>
#include<algorithm>//算法 头文件
//统计自定义数据类型
class Person{
public:
Person(string name,int age){
this->m_Name=name;
this->m_Age=age;
}
string m_Name;
int m_Age;
};
class AgeGreater20{
public:
// 谓词(返回bool类型的仿函数)
bool operator()(const Person &p){
return p.m_Age>20;
}
};
void test02(){
vector<Person>v;
Person p1("刘备",35);
Person p2("关羽",35);
Person p3("张飞",35);
Person p4("赵云",30);
Person p5("曹操",20);
//将人员插入在容器中
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
v.push_back(p5);
//统计 大于20岁人员个数
int num=count_if(v.begin(),v.end(),AgeGreater20());//谓词
cout<<"大于20岁的人员个数为:"<<num<<endl;
}
int main()
{
test02();
system("pause");
}