函数对象
1. 函数对象(仿函数)
- 函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
- 函数对象可以有自己的状态
- 函数对象可以作为参数传递(实际上是类的对象作为参数)
#include<iostream>
using namespace std;
#include<string>
//1. 函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
class MyAdd
{
public:
int operator()(int v1,int v2)
{
return v1 + v2;
}
};
void test01()
{
MyAdd myadd;
cout << myadd(2, 2) << endl;
}
//2. 函数对象可以有自己的状态
class Myprint
{
public:
Myprint() :count(0) {}
void operator()(string test)
{
cout << test << endl;
count++;
}
public:
int count;//内部自己的状态
};
void test02()
{
Myprint myprint;
myprint("rookie");
myprint("rookie");
myprint("rookie");
cout << "打印次数为" << myprint.count<<endl;
}
//3.函数对象可以作为参数传递
void doPrint(Myprint& mp, string test)
{
mp(test);
}
void test03()
{
Myprint myprint2;
doPrint(myprint2, "RRRRRRRRookie");
}
int main() {
srand((unsigned int)time(NULL));
//test01();
//test02();
test03();
system("pause");
return 0;
};
2. 谓词
- 返回bool类型的仿函数成为谓词
- 按照operator()接受的参数个数,一元谓词,二元谓词
- 用谓词自定义set排序方式
set<Person, ComparePerson> s;
- 一元谓词 用于查询vector元素
vector<int> v;
//.....添加数据
//查找元素
vector<int>::iterator it = find_if(v.begin(), v.end(),MyCompare());
if (it != v.end())
{
cout << "找到了XXX的数字" << *it << endl;
}
- 二元谓词 自定义sort()函数排序方式
vector<int> v;
//.....添加数据
//用谓词定义sort排序方法
sort(v.begin(), v.end(), myCompare());
3.内建函数对象
头文件#include<functional>
`6个算数类函数对象,除了negate是一元运算,其他都是二元运算。
template<class T> T plus<T>// 加 法 仿 函 数
template<class T> T minus<T>// 减 法 仿 函 数
template<class T> T multiplies<T>// 乘 法 仿 函 数
template<class T> T divides<T>// 除 法 仿 函 数
template<class T> T modulus<T>// 取 模 仿 函 数
template<class T> T negate<T>// 取 反 仿 函 数`
`6个关系运算类函数对象,每一种都是二元运算。
template<class T> bool equal_to<T>// 等 于
template<class T> bool not_equal_to<T>// 不 等 于
template<class T> bool greater<T>// 大 于 常用!
template<class T> bool greater_equal<T>// 大 于 等 于
template<class T> bool less<T>// 小 于
template<class T> bool less_equal<T>// 小 于 等 于`
`逻辑运算类运算函数,not为一元运算,其余为二元运算。
template<class T> bool logical_and<T>// 逻 辑 与
template<class T> bool logical_or<T>// 逻 辑 或
template<class T> bool logical_not<T>// 逻 辑 非`
3.1 STL仿函数例子
#include<iostream>
using namespace std;
#include<functional>
#include<vector>
#include<algorithm>
//内建函数对象 算术仿函数
void test01()
{
//negate 一元仿函数 取反
negate<int>n;
cout << n(50) << endl;
//plus 二元仿函 相加
plus<int>p;
cout << p(10,20) << endl;
//greater 关系仿函数 大于
vector<int> v;
v.push_back(10);
v.push_back(28);
v.push_back(22);
sort(v.begin(), v.end(), greater<int>());
cout << *v.begin() << endl;
//logical_not 逻辑非
vector<bool>vb;
vb.push_back(true);
vb.push_back(false);
vb.push_back(true);
cout << *vb.begin() << endl;
/*搬到vb2,并执行取反操作; 搬运前需要提前对vector开辟空间*/
vector<bool>vb2;
vb2.resize(vb.size());
transform(vb.begin(), vb.end(), vb2.begin(), logical_not<bool>());
cout << *vb2.begin() << endl;
}
int main() {
test01();
system("pause");
return 0;
};
常用算法
4. 遍历
for_each
for_each(v.begin(), v.end(), print01);//对于一般函数
for_each(v.begin(), v.end(), print01());//对于仿函数
transform 搬运
注意提前在vb2容器开辟空间
transform(vb.begin(), vb.end(), vb2.begin(), logical_not<bool>());
5. 查找
find()
- 查找指定元素,找到返回指定元素的迭代器,找不到返回结束迭代器end();
- find(iterator beg,iterator end,value);
//按值查找,value为要查找的元素;
注意查找自定义类型时,重载==,让底层知道怎么找
find_if() 条件查找
- find_if(iterator beg,iterator end, _pred);
//按条件查找元素
// _pred为普通函数或者谓词(返回bool类型的仿函数)
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<string>
class Person
{
public:
string m_Name;
int m_Age;
Person(string name, int age) :m_Name(name), m_Age(age) {}
};
// 定义谓词
class Greater20
{
public:
bool operator()(Person &p)
{
return p.m_Age > 20;
}
};
void test01()
{
//1.创建容器 添加数据
vector<Person>v;
Person p1("aaa", 10);
Person p2("bbb", 20);
Person p3("ccc", 30);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
//2.找年龄大于20的人
auto it=find_if(v.begin(), v.end(), Greater20());
if (it != v.end())
{
cout << (*it).m_Name << " " << (*it).m_Age<<endl;
}
}
int main() {
test01();
system("pause");
return 0;
};
adjacent_find 查找相邻重复元素
- adjacent_find (iterator beg, iterator end);
//查找相邻重复元素,返回相邻元素的第一个位置的迭代器
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
void test()
{
vector<int>v;
v.push_back(10);
v.push_back(5);
v.push_back(8);
v.push_back(8);
v.push_back(10);
v.push_back(2);
v.push_back(22);
vector<int>::iterator it = adjacent_find(v.begin(), v.end());//迭代器接收
if (it == v.end())
{
cout << "未找到相邻重复元素" << endl;
}
else
{
cout << "找到相邻重复元素" << *it << endl;
}
}
int main()
{
test();
system("pause");
return 0;
}
binary_search 二分查找 查找指定元素是否存在
- bool binary_search(iterator beg, iterator end, value);
- 二分查找,必须对容器是有序的序列
- 如果是无需系列,不能用二分查找!!!
count 和count_if
和find一样,不过返回值为 int类型
6.排序
sort
- sort(iterator beg, iterator end,_pred);
(非常常用的算法,一定要熟练掌握)
//按值查找元素,找到返回指定位置的迭代器,找不到则返回结束迭代器的位置 - 1)_pred默认是升序排序
- 2)改为降序排列
使用内建的函数对象greater,当然也可以自己写一个仿函数
random_shuffle 洗牌 指定范围内的元素随机调整次序
random_shuffle(iterator beg, iterator end);
注意放随机数种子
merge 两个容器元素合并,并存储到另一容器中
- merge(iterator beg1,iterator end1,iterator beg2,iterator end2,iterator dest);
//目标容器开始迭代器
- 注意:(目标容器要提前开辟内存空间)
v3.resize(v1.size()+v2.size());
- 两个容器必须是有序的,要么都是升序,要么都是降序才行
reverse 将容器内元素进行反转
reverse(iterator beg, iterator end);
7.拷贝和替换
copy
copy(iterator beg, iterator end, iterator dest);
//相当于赋值操作,实际应用中不常用
replace 和replace_if
- 将范围内的旧元素修改为新元素
replace(iterator beg, iterator end, old value, new value); - 将范围内满足条件的旧元素修改为新元素
replace_if (iterator beg, iterator end, _pred, new value);
swap
swap(container c1,container c2);
- 互换两个相同类型的容器内容
- 容器大小不一样 也是可以互换的
8. 算术生成算法
accumulate累加
- 头文件
#include<numeric>
- accumulate(iterator beg, iterator end, value);
//value为起始的累加值(是额外的),相当于初值;
fill填充
- fill(iterator beg, iterator end, value);
//将容器区间内的元素值填充为指定的值
9.常用集合算法
set_intersection 求两个容器的交集放到目标容器
- set_intersection(iterator beg1,iterator end1,iterator beg2,iterator end2,iterator dest);
- 两个集合必须是有序序列
- 目标容器开辟空间需要从两个容器中取小值
- set_intersection返回值是交集中最后一个元素的位置,而不是容器r的end()!!!
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class myPrint
{
public:
void operator()(int val)
{
cout << val << " ";
}
};
void test()
{
vector<int>v1;
vector<int>v2;
v1.resize(4, 1);
v2.resize(4, 1);
fill(v1.begin(), v1.end(), 1);
fill(v2.begin()+2, v2.end(), 2);
vector<int> vTarget;
//目标容器需要开辟空间,交集 取小即可
vTarget.resize(min(v1.size(), v2.size()));
//获取交集,返回 交集中结束位置的迭代器
auto itEnd=set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
for_each(vTarget.begin(), itEnd, myPrint());
cout << endl;
}
int main()
{
test();
system("pause");
return 0;
}
set_union 求两个容器的并集
- set_union(iterator beg1,iterator end1,iterator beg2,iterator end2,iterator dest);
- 返回一个迭代器 位置是并集的最后一个元素的迭代器,而不是容器r的end()!!!
- 目标容器开辟相加的空间(最大情况)
set_union 求两个容器的差集
- set_difference(iterator beg1,iterator end1,iterator beg2,iterator end2,iterator dest);
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
void myPrint(int val)
{
cout << val << " ";
}
void test()
{
vector<int>v1;
vector<int>v2;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
v2.push_back(i + 5);
}
vector<int>v3;
//最坏的情况 没有一点交集 取最大的那个容器
v3.resize(max(v1.size(), v2.size()));
cout << "v1和v2的差集为:" << endl;
vector<int>::iterator itEnd = set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());//返回差集结束的位置
for_each(v3.begin(), itEnd, myPrint);
cout << endl;
cout << "v2和v1的差集为:" << endl;
vector<int>::iterator itEnd2 = set_difference(v2.begin(), v2.end(), v1.begin(), v1.end(), v3.begin());
for_each(v3.begin(), itEnd2, myPrint);
cout << endl;
}
int main()
{
test();
system("pause");
return 0;
}