一、STL函数对象的概念。
1、概念。
重载函数调用操作符的类,其对象称为函数对象。
函数对象使用重载()时,行为类似函数调用,也叫仿函数。
2、本质。
函数对象(仿函数)是一个类的对象,不是一个函数。
例如:
class Person{
public:
void operator()()
{
}
};
Person p; //p就是函数对象
p(); //对象使用()时,非常像函数调用 -> 仿函数
二、函数对象的使用。
1、函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值。
2、函数对象超过普通函数的概念,函数对象可以有自己的状态。
3、函数对象可以作为参数传递。
#include
using namespace std;
/*
1、函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值。
2、函数对象超过普通函数的概念,函数对象可以有自己的状态。
3、函数对象可以作为参数传递。
*/
//1. 函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值。
class MyAdd{
public:
//类中重载了(),那么这个类的对象,就是函数对象。
int operator()(int v1,int v2)
{
return v1 + v2;
}
};
void test01()
{
MyAdd myadd; //myadd就是一个函数对象
int ret = myadd(10,20);
cout << "ret = " << ret << endl; //30
}
//2. 函数对象超过普通函数的概念,函数对象可以有自己的状态。
class Myprint{
public:
Myprint()
{
this->count = 0;
}
void operator()(string text)
{
cout << text << endl;
this->count++;
}
int count;
};
void test02()
{
Myprint myprint;
myprint("helloworld");
myprint("helloworld");
myprint("helloworld");
myprint("helloworld");
myprint("helloworld");
myprint("helloworld");
myprint("helloworld");
myprint("helloworld");
cout << "myprint调用的次数是:" << myprint.count << endl;
}
//3. 函数对象可以作为参数传递。
void doPrint(Myprint &mp,string text)
{
mp(text);
}
void test03()
{
Myprint myprint;
doPrint(myprint,"hello C++");
}
int main()
{
//test01();
//test02();
test03();
return 0;
}
三、谓词的概念。
概念:
返回bool类型的仿函数称为谓词。
如果operator()接受一个参数,那么叫做一元谓词。
如果operator()接受二个参数,那么叫做二元谓词。1、一元谓词。
#include
using namespace std;
#include
#include
//一元谓词。
class GreaterFive{
public:
bool operator()(int val)
{
return val > 5;
}
};
int main()
{
vector v;
int i;
for(i=0;i<10;i++)
{
v.push_back(i); //0~9
}
//查找一下容器中有没有大于5的数字。
//GreaterFive greaterFive;
//vector::iterator it = find_if(v.begin(),v.end(),greaterFive); //填有名函数对象
vector::iterator it = find_if(v.begin(),v.end(),GreaterFive()); //填匿名函数对象
if(it == v.end())
{
cout << "未找到" << endl;
}
else{
cout << "找到了大于5的数字:" << *it << endl;
}
return 0;
}
2、二元谓词。
#include
using namespace std;
#include
#include
//二元谓词。
class Mycompare{
public:
bool operator()(int v1,int v2)
{
return v1 > v2;
}
};
int main()
{
vector v;
v.push_back(10);
v.push_back(40);
v.push_back(20);
v.push_back(30);
v.push_back(50);
sort(v.begin(),v.end()); //默认是升序的。
for(vector::iterator it = v.begin();it!=v.end();it++)
{
cout << *it << " ";
}
cout << endl;
//使用函数对象,改变算法策略,使得排序规则从大到小。
//Mycompare mycompare;
//sort(v.begin(),v.end(),mycompare);
sort(v.begin(),v.end(),Mycompare());
for(vector::iterator it = v.begin();it!=v.end();it++)
{
cout << *it << " ";
}
cout << endl;
return 0;
}
练习: 使用sort算法来对Person自定义类型进行排序。
Person 姓名和年龄
#include
using namespace std;
#include
#include
class Person{
public:
Person(string name,int age)
{
this->m_Name = name;
this->m_Age = age;
}
string m_Name;
int m_Age;
};
class Comparetest{
public:
bool operator()(Person &p1,Person &p2)
{
return p1.m_Age > p2.m_Age;
}
};
int main()
{
vector v;
Person p1("刘备",40);
Person p2("关羽",50);
Person p3("张飞",35);
Person p4("赵云",20);
Person p5("曹操",38);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
v.push_back(p5);
cout << "排序前:" << endl;
for(vector::iterator it = v.begin();it!=v.end();it++)
{
cout << "姓名:" << it->m_Name << " 年龄:" << it->m_Age << endl;
}
//Comparetest c;
//sort(v.begin(),v.end(),c);
sort(v.begin(),v.end(),Comparetest());
cout << "排序后:" << endl;
for(vector::iterator it = v.begin();it!=v.end();it++)
{
cout << "姓名:" << it->m_Name << " 年龄:" << it->m_Age << endl;
}
return 0;
}
四、内建函数对象。
1、意义:
STL中已经内建一些函数对象。
2、分类。
算术仿函数。
关系仿函数。
逻辑仿函数。
3、用法。
这些仿函数所产生的对象,用法与一般函数完全相同。
使用内建函数对象,需要引入头文件:#include
五、算术仿函数。
template
template
template
template
template
template
其中:negate是一元运算,其他都是二元运算。
#include
using namespace std;
int main()
{
plus p;
cout << p(10,20) << endl;
negate n; n就是一个函数对象
cout << n(50) << endl;
return 0;
}
六、关系仿函数。
template
template
template
template
template
template
#include
using namespace std;
#include
#include
/*
class Mycompare{
public:
bool operator()(int v1,int v2)
{
return v1 > v2;
}
};
*/
int main()
{
vector v;
v.push_back(10);
v.push_back(50);
v.push_back(30);
v.push_back(40);
v.push_back(20);
cout << "排序前:" << endl;
for(vector::iterator it = v.begin() ;it != v.end() ;it++)
{
cout << *it << " ";
}
cout << endl;
//sort(v.begin(),v.end()); //默认是升序的。
//sort(v.begin(),v.end(),Mycompare()); //自己写规则,按照降序来排序。
//sort(v.begin(),v.end(),greater()); //使用内建函数对象
cout << "排序后:" << endl;
for(vector::iterator it = v.begin() ;it != v.end() ;it++)
{
cout << *it << " ";
}
cout << endl;
return 0;
}
七、逻辑仿函数。
template
template
template
#include
using namespace std;
#include
#include
//逻辑仿函数
int main()
{
vector v;
v.push_back(true); //1
v.push_back(false); //0
v.push_back(true); //1
v.push_back(false); //0
cout << "搬运前:" << endl;
for(vector::iterator it = v.begin() ;it!=v.end() ;it++)
{
cout << *it << " "; //1 0 1 0
}
cout << endl;
vector v2;
v2.resize(v.size());
logical_not ln;
transform(v.begin(),v.end(),v2.begin(),ln);
cout << "搬运后:" << endl;
for(vector::iterator it = v2.begin() ; it!=v2.end() ; it++)
{
cout << *it << " ";
}
cout << endl;
return 0;
}
八、常见遍历算法。
算法简介:
for_each //遍历容器
transform //搬运容器到另一个容器中
#include
using namespace std;
#include
#include
//常见遍历算法。
//for_each //遍历容器
//transform //搬运容器到另一个容器中
class Print01{
public:
void operator()(int val)
{
cout << val << " ";
}
};
void Print02(int val)
{
cout << val << " ";
}
class Test{
public:
int operator()(int v)
{
return v + 100;
}
};
int myTest(int v)
{
return v + 100;
}
int main()
{
vector v;
int i;
for(i=0;i<10;i++)
{
v.push_back(i);
}
//第一种方式: 使用有名函数对象
//Print01 p1;
//for_each(v.begin(),v.end(),p1);
//第二种方式: 使用匿名函数对象
//for_each(v.begin(),v.end(),Print01());
//第三种方式:使用函数
for_each(v.begin(),v.end(),Print02);
cout << endl;
cout << "--------------------------" << endl;
vector vTarget; //目标
vTarget.resize(v.size());
//transform(v.begin(),v.end(),vTarget.begin(),Test());
transform(v.begin(),v.end(),vTarget.begin(),myTest);
for_each(vTarget.begin(),vTarget.end(),Print02);
cout << endl;
return 0;
}
九、常见查找算法。
find //查找元素
find_if //按条件查找元素
#include
using namespace std;
#include
#include
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;
}
else{
return false;
}
}
string m_Name;
int m_Age;
};
class Greater20{
public:
bool operator()(Person &p)
{
return p.m_Age > 20;
}
};
bool Greater20func(Person &p)
{
return p.m_Age > 20;
}
int main()
{
/*
vector v;
int i;
for(i=0;i<10;i++)
{
v.push_back(i);
}
//查找一下有没有5这个元素。
vector::iterator it = find(v.begin(),v.end(),5);
if(it == v.end())
{
cout << "未找到" << endl;
}
else{
cout << "找到了:" << *it << endl;
}
*/
vector v;
Person p1("aaa",10);
Person p2("bbb",20);
Person p3("ccc",30);
Person p4("ddd",40);
Person p5("eee",50);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
v.push_back(p5);
/*
vector::iterator it = find(v.begin(),v.end(),p2);
if(it == v.end())
{
cout << "未找到" << endl;
}
else{
cout << "找到了:" << "姓名:"<< it->m_Name << "年龄:" << it->m_Age << endl;
}
*/
//vector::iterator it = find_if(v.begin(),v.end(),Greater20());
vector::iterator it = find_if(v.begin(),v.end(),Greater20func);
if(it == v.end())
{
cout << "未找到" << endl;
}
else{
cout << "找到了:" << "姓名:"<< it->m_Name << "年龄:" << it->m_Age << endl;
}
return 0;
}
十、常见查找算法。
#include
using namespace std;
#include
#include
int main()
{
/*
vector v;
v.push_back(0);
v.push_back(2);
v.push_back(0);
v.push_back(3);
v.push_back(3);
v.push_back(1);
v.push_back(3);
v.push_back(4);
v.push_back(9);
v.push_back(9);
v.push_back(10);
v.push_back(7);
vector::iterator it = adjacent_find(v.begin(),v.end());
if(it == v.end())
{
cout << "未找到相邻的元素" << endl;
}
else{
cout << "找到相邻的元素:" << *it < v;
int i;
for(i=0;i<10;i++)
{
v.push_back(i);
}
v.push_back(2);
bool ret = binary_search(v.begin(),v.end(),9);
if(ret)
{
cout << "找到了元素" << endl;
}
else{
cout << "没有找到元素" << endl;
}
return 0;
}
十一、常见查找算法。
#include
using namespace std;
#include
#include
class Greater20{
public:
bool operator()(int val) // Person&p
{
return val > 20; //return p.m_Age > 20
}
};
int main()
{
vector v;
v.push_back(10);
v.push_back(30);
v.push_back(20);
v.push_back(30);
v.push_back(30);
v.push_back(40);
//统计30出现的次数。
int num = count(v.begin(),v.end(),30);
cout << "num = " << num << endl;
//统计大于20有多少个。
num = count_if(v.begin(),v.end(),Greater20());
cout << "num = " << num << endl;
return 0;
}
十二、常见排序算法。
#include
using namespace std;
#include
#include
class myprint{
public:
void operator()(int val)
{
cout << val << " ";
}
};
int main()
{
/*
srand(time(NULL));
vector v;
int i;
for(i=0;i<10;i++)
{
v.push_back(i);
}
cout << "洗牌前:" << endl;
for_each(v.begin(),v.end(),myprint());
cout << endl;
random_shuffle(v.begin(),v.end()); //内部实现利用rand()来实现的。
cout << "洗牌前:" << endl;
for_each(v.begin(),v.end(),myprint());
cout << endl;
*/
vector v1;
vector v2;
int i;
for(i=0;i<10;i++)
{
v1.push_back(i); //0~9
v2.push_back(i+1); //1~10
}
vector vTarget;
vTarget.resize(v1.size()+v2.size());
merge(v1.begin(),v1.end(),v2.begin(),v2.end(),vTarget.begin());
for_each( vTarget.begin() , vTarget.end() , myprint());
cout << endl;
cout << "反转前:" << endl;
for_each(v1.begin(),v1.end(),myprint());
cout << endl;
reverse(v1.begin(),v1.end());
cout << "反转后:" << endl;
for_each(v1.begin(),v1.end(),myprint());
cout << endl;
return 0;
}
十三、常见拷贝和替换算法。
#include
using namespace std;
#include
#include
class myprint{
public:
void operator()(int val)
{
cout << val << " ";
}
};
class Greater30{
public:
bool operator()(int val)
{
return val >= 30;
}
};
int main()
{
vector v1;
v1.push_back(10);
v1.push_back(50);
v1.push_back(30);
v1.push_back(60);
v1.push_back(30);
v1.push_back(40);
v1.push_back(20);
v1.push_back(10);
v1.push_back(30);
vector v2;
v2.resize(v1.size());
copy(v1.begin(),v1.end(),v2.begin());
for_each(v2.begin(),v2.end(),myprint());
cout << endl;
cout << "替换前:" << endl;
for_each(v1.begin(),v1.end(),myprint());
cout << endl;
//replace(v1.begin(),v1.end(),30,70);
replace_if(v1.begin(),v1.end(),Greater30(),100);
cout << "替换后:" << endl;
for_each(v1.begin(),v1.end(),myprint());
cout << endl;
cout << "互换前:" << endl;
for_each(v1.begin(),v1.end(),myprint());
cout << endl;
for_each(v2.begin(),v2.end(),myprint());
cout << endl;
swap(v1,v2);
cout << "互换后:" << endl;
for_each(v1.begin(),v1.end(),myprint());
cout << endl;
for_each(v2.begin(),v2.end(),myprint());
cout << endl;
return 0;
}
十四、常见算术生成算法。
需要包含头文件:#include
#include
using namespace std;
#include
#include
#include
class myprint{
public:
void operator()(int val)
{
cout << val << " ";
}
};
int main()
{
/*
vector v;
int i;
for(i=0;i<100;i++)
{
v.push_back(i);
}
int sum = accumulate(v.begin(),v.end(),0);
cout << sum << endl;
*/
vector v;
v.resize(10);
fill(v.begin(),v.end(),100);
for_each(v.begin(),v.end(),myprint());
cout << endl;
return 0;
}
十五、常见集合算法。
#include
using namespace std;
#include
#include
class myprint{
public:
void operator()(int val)
{
cout << val << " ";
}
};
int main()
{
vector v1;
vector v2;
int i;
for(i=0;i<10;i++)
{
v1.push_back(i); // 0 1 2 3 4 5 6 7 8 9
v2.push_back(i+5); // 5 6 7 8 9 10 11 12 13 14
}
//求交集。
//vector vTarget; //存放交集结果
//vTarget.resize(min(v1.size(),v2.size()));
//返回值:是交集中最后一个元素的迭代器。
//vector::iterator itEnd = set_intersection(v1.begin(),v1.end(),v2.begin(),v2.end(),vTarget.begin());
//for_each(vTarget.begin(),itEnd,myprint());
//cout << endl;
//求并集。
//vector vTarget;
//vTarget.resize(v1.size() + v2.size());
//vector::iterator itEnd = set_union(v1.begin(),v1.end(),v2.begin(),v2.end(),vTarget.begin());
//for_each(vTarget.begin(),itEnd,myprint());
//cout << endl;
//求v1与v2的差集。
vector vTarget;
vTarget.resize(max(v1.size(),v2.size()));
//vector::iterator itEnd = set_difference(v1.begin(),v1.end(),v2.begin(),v2.end(),vTarget.begin());
vector::iterator itEnd = set_difference(v2.begin(),v2.end(),v1.begin(),v1.end(),vTarget.begin());
for_each(vTarget.begin(),itEnd,myprint());
cout << endl;
return 0;
}