C++提高编程-STL(仿函数、方法)
函数对象
函数对象基本概念
函数对象\仿函数是一个东西,本质是一个类的对象,这个类的特殊在于重载了函数调用操作符()。因为使用重载()的行为,很像函数调用,所以也叫就成为函数对象或者仿函数。
函数对象的使用
class MyAdd
{
public:
int operator()(const int &a,const int& b)
{
return a + b;
}
};
void AddTest(MyAdd& md,const int& a,const int& b)
{
cout << md(a, b) << endl;
}
void test()
{
//1.函数对象可以像普通函数一样调用,可以有参数,可以有返回值。
MyAdd myadd;
cout << myadd(10, 20) << endl;
//2.函数对象有自己的状态,???没太搞懂,先空着
//3.函数对象可以作为参数传递,这个就当作正常的类的对象的传递即可。
AddTest(myadd, 10, 20);
}
谓词概念
一元谓词代码实例:
//返回的是布尔类型的仿函数,称为谓词
//根据参数列表的不同,一个参数为一元谓词,二个参数为二元谓词
class Great
{
public:
bool operator()(const int& a) //一个参数为一元谓词
{
return a > 5;
}
};
void test()
{
vector<int> v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
//用find_if方法查找大于5的数字,提示_pr_pred说明要谓词 //采用匿名对象的方式
vector<int>::iterator it = find_if(v.begin(), v.end(), Great());
cout << *it << endl;
}
二元谓词代码示例:
//返回的是布尔类型的仿函数,称为谓词
//根据参数列表的不同,一个参数为一元谓词,二个参数为二元谓词
class Great
{
public:
bool operator()(const int& a, const int &b) //二个参数为二元谓词
{
return a > b;
}
};
void test()
{
vector<int> v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
//想用sort实现从大到小排序,采用谓词改变排序规则
sort(v.begin(), v.end(), Great());
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << endl;
}
}
内建函数对象
算术仿函数
//内建函数对象
//negate,一元取反函数
negate<int>n;
cout << n(50) << endl;
//plus,二元加法函数
plus<int> pl;
cout << pl(10, 20) << endl;
关系仿函数
//内建函数对象
//大于
vector<int>v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
//想要让其降序排列,可以使用内建函数对象,great
sort(v.begin(), v.end(), greater<int>());
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << endl;
}
逻辑仿函数
//内建函数对象
//逻辑非
vector<bool>v1;
for (int i = 0; i < 5; i++)
{
v1.push_back(i%2);
}
cout << "最初数据:" << endl;
for (vector<bool>::iterator it = v1.begin(); it != v1.end(); it++)
{
cout << *it << endl;
}
//将v1中的数据搬到v2中,并全部取非
vector<bool> v2;
v2.resize(v1.size());
transform(v1.begin(), v1.end(), v2.begin(), logical_not<bool>());
cout << "搬运后的数据:" << endl;
for (vector<bool>::iterator it = v2.begin(); it != v2.end(); it++)
{
cout << *it << endl;
}
STL常用算法
常用遍历算法-for_each和transform
//全局函数
void print01(const int& val)
{
cout << val << ' ';
}
//仿函数
class print02
{
public:
void operator()(const 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;
}
class MyTransform
{
public:
int operator()(const int &val)
{
return val + 10;
}
};
//仿函数
class MyPrint
{
public:
void operator()(const int& val)
{
cout << val << ' ';
}
};
void test01()
{
vector<int>v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
vector<int>target;
target.resize(v.size());
//transform四个参数分别为,要被搬运容器的起止迭代器以及要放入容器的开始迭代器以及函数对象或函数名
//注意这里只需要放入容器的开始迭代器,所以需要保证放入迭代器提前有这么大的空间.
transform(v.begin(), v.end(), target.begin(),MyTransform());
//使用函数对象
for_each(target.begin(), target.end(), MyPrint());
cout << endl;
}
常用查找算法
find
class Person
{
public:
Person(string name, int age)
{
this->m_Age = age;
this->m_Name = name;
}
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 test01()
{
//使用find查找内置数据类型
vector<int>v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
//find的三个参数分别为起止迭代器以及要查找的值。
vector<int>::iterator it = find(v.begin(), v.end(), 5);
//没有找到返回end();
if (it == v.end())
{
cout << "没有找到5" << endl;
}
else
{
cout << "找到5了" << endl;
}
cout << endl;
//使用find查找自定义类
vector<Person>vp;
Person p1("张三", 3);
Person p2("李四", 4);
Person p3("王五", 5);
Person p4("赵六", 6);
vp.push_back(p1);
vp.push_back(p2);
vp.push_back(p3);
vp.push_back(p4);
//自定义数据类型的查找需要重载==号。
vector<Person>::iterator It = find(vp.begin(), vp.end(), Person("李四", 4));
if (It == vp.end())
{
cout << "没有找到李四" << endl;
}
else
{
cout << "找到李四了" << endl;
}
}
find_if
//写大于5的仿函数
class GreatFive
{
public:
bool operator()(const int& val)
{
return val > 5;
}
};
//自定义类
class Person
{
public:
Person(string name, int age)
{
this->m_Age = age;
this->m_Name = name;
}
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;
};
class GreatTen
{
public:
bool operator()(const Person& p)
{
return p.m_Age > 10;
}
};
void test01()
{
//使用find_if查找内置数据类型
vector<int>v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
//find_if的三个参数分别为起止迭代器以及要函数对象\函数名
vector<int>::iterator it = find_if(v.begin(), v.end(), GreatFive());
//没有找到返回end();
if (it == v.end())
{
cout << "没有找到大于5" << endl;
}
else
{
cout << "找到了大于5的值" << endl;
cout << "其值为:" << *it << endl;
}
cout << endl;
//使用find查找自定义类
vector<Person>vp;
Person p1("张三", 3);
Person p2("李四", 4);
Person p3("王五", 21);
Person p4("赵六", 26);
vp.push_back(p1);
vp.push_back(p2);
vp.push_back(p3);
vp.push_back(p4);
//自定义数据类型的查找需要重载==号。
vector<Person>::iterator It = find_if(vp.begin(), vp.end(), GreatTen());
if (It == vp.end())
{
cout << "没有找到年龄大于20的" << endl;
}
else
{
cout << "找到年龄大于20的" << endl;
cout << "姓名:" << It->m_Name << ",年龄为:" << It->m_Age << endl;
}
}
adjacent_find
//使用adjacent_find查找相邻重复元素,找到返回第一个迭代器,没找到返回end
vector<int>v;
v.push_back(0);
v.push_back(1);
v.push_back(2);
v.push_back(2);
v.push_back(1);
v.push_back(0);
//两个参数分别为起止迭代器.
vector<int>::iterator it = adjacent_find(v.begin(), v.end());
if (it == v.end())
{
cout << "没有找到相邻重复元素" << endl;
}
else
{
cout << "找到了相邻重复元素" << endl;
cout << "相邻的值为:" << *it << endl;
}
binary_search
//使用binary_search查找元素,binary_search必须是自然上升子序列才可
vector<int>v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
//两个参数分别为起止迭代器.
bool it = binary_search(v.begin(), v.end(), 9);
if (it)
{
cout << "找到元素9" << endl;
}
else
{
cout << "没找到元素9" << endl;
}
count
v//使用count统计元素
vector<int>v;
v.push_back(0);
v.push_back(1);
v.push_back(0);
v.push_back(1);
int cnt = count(v.begin(), v.end(), 0);
cout << "0的数量是:" << cnt << endl;
count_if
//写大于5的仿函数
class GreatFive
{
public:
bool operator()(const int& val)
{
return val > 5;
}
};
void test01()
{
//使用count_if统计元素
vector<int>v;
v.push_back(10);
v.push_back(12);
v.push_back(0);
v.push_back(6);
int cnt = count_if(v.begin(), v.end(), GreatFive());
cout << "大于5的数量是:" << cnt << endl;
}
常用排序算法
sort
void myprint(const int &val)
{
cout << val << ' ';
}
void test01()
{
//使用sort排序元素
vector<int>v;
v.push_back(10);
v.push_back(12);
v.push_back(0);
v.push_back(6);
//采用sort,实现大于排序,采用内置函数对象greater
sort(v.begin(), v.end(), greater<int>());
//采用for_each + 全局函数快速打印
for_each(v.begin(), v.end(), myprint);
}
random_shuffle
//使用random_shuffle打乱元素
vector<int>v;
v.push_back(10);
v.push_back(12);
v.push_back(0);
v.push_back(6);
//采用sort,实现大于排序,采用内置函数对象greater
sort(v.begin(), v.end(), greater<int>());
//不提供随机种子就是伪随机
srand((unsigned)time(0));//添加当前时间作为随机的参数,防止伪随机
random_shuffle(v.begin(), v.end());
//采用for_each + 全局函数快速打印
for_each(v.begin(), v.end(), myprint);
merge
//使用merge合并元素,两个有序数组合并成一个新的有序数组,有点像归并排序
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快速打印。
for_each(target.begin(), target.end(), myprint);
reverse
//使用reverse反转元素
vector<int>v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
cout << "反转前:";
for_each(v1.begin(), v1.end(), myprint);
cout << endl;
reverse(v1.begin(), v1.end());
cout << "反转后:";
for_each(v1.begin(), v1.end(), myprint);
cout << endl;
常用拷贝和替换算法
copy
//copy复制
vector<int>v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
vector<int>target;
target.resize(v.size());
//感觉copy和transfomr的区别在于copy就纯复制粘贴,而trangform则可以在
//搬运途中顺便做一些操作。
copy(v.begin(), v.end(), target.begin());
for_each(target.begin(), target.end(), MyPrint());
replace
//replace替换
vector<int>v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
//四个参数分别为起止迭代器,旧元素的值->需要替换成的新元素的值
replace(v.begin(), v.end(), 2, 200);
for_each(v.begin(), v.end(), MyPrint());
replace_if
//replace_if替换
vector<int>v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
//四个参数分别为起止迭代器,谓语,用以筛选符合条件的数,和替换成的值
replace_if(v.begin(), v.end(), GreatFive(), 200);
for_each(v.begin(), v.end(), MyPrint());
swap
常用算术生成算法
accmulate
//accumulate计算累加和
vector<int>v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
//三个参数依次为起止迭代器和起始值
int total = accumulate(v.begin(), v.end(), 1000);
cout << "total = " << total << endl;
fill
//fill填充
vector<int>v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
//三个参数分别代表起止迭代器和要填充的值
fill(v.begin() + 4, v.end(), 1000);
for_each(v.begin(), v.end(), MyPrint());
常用集合算法
set_intersection
//set_intersection,求交集操作
vector<int>v1,v2;
for (int i = 0; i < 10; i++)
{
v1.push_back(i); //范围:0~9
v2.push_back(i + 5); //范围:5~14
}
//将交集放入dest中
vector<int>dest;
dest.resize(min(v1.size(),v2.size()));
//五个参数依次为求交集的两个容器的起止迭代器以及终点容器的起始迭代器
//返回结果为求完交集后,放入dest后的终止迭代器
//要求要求交集的两个集合得是有序的才可,和底层实现有关
vector<int>::iterator it = set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), dest.begin());
for_each(dest.begin(), it, MyPrint());
set_union
//set_union,求并集操作
vector<int>v1,v2;
for (int i = 0; i < 10; i++)
{
v1.push_back(i); //范围:0~9
v2.push_back(i + 5); //范围:5~14
}
//将交集放入dest中
vector<int>dest;
dest.resize(v1.size() + v2.size());
//五个参数依次为求交集的两个容器的起止迭代器以及终点容器的起始迭代器
//返回结果为求完交集后,放入dest后的终止迭代器
//要求要求并集的两个集合得是有序的才可,和底层实现有关
vector<int>::iterator it = set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), dest.begin());
for_each(dest.begin(), it, MyPrint());
set_difference
//set_difference,求差集操作
vector<int>v1,v2;
for (int i = 0; i < 10; i++)
{
v1.push_back(i); //范围:0~9
v2.push_back(i + 5); //范围:5~14
}
//将交集放入dest中
vector<int>dest;
dest.resize(v1.size());
//五个参数依次为求交集的两个容器的起止迭代器以及终点容器的起始迭代器
//返回结果为求完差集后,放入dest后的终止迭代器
//要求要求差集的两个集合得是有序的才可,和底层实现有关
vector<int>::iterator it = set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), dest.begin());
for_each(dest.begin(), it, MyPrint());