1.STL函数对象
1.1函数对象
1.1.1函数对象概念
1.概念
- 重载函数调用操作符的类,其对象称为函数对象
- 函数对象在使用重载的()时,行为类似函数调用,也叫仿函数
2.本质
1.1.2函数对象使用
- 特点
- 函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
- 函数对象超出普通函数的概念,函数对象可以有自己的状态
- 函数对象可以作为参数传递
#include<iostream>
using namespace std;
class Add
{
public:
int operator()(int v1, int v2)
{
return v1 + v2;
}
};
class MyPrint
{
public:
MyPrint() {
this->count = 0;
}
void operator()(string str)
{
cout << "需要打印的信息: " << str << endl;
this->count++;
}
int count;
};
void doPrint(MyPrint& mp, string str)
{
mp(str);
}
void test()
{
Add add;
int num1 = add(10, 20);
cout << "和为: " << num1 << endl;
MyPrint myPrint;
myPrint("C++");
MyPrint mp;
doPrint(mp, "C");
}
int main()
{
test();
system("pause");
return 0;
}
1.2谓词
1.2.1概念
- 概念
- 返回bool类型的仿函数称为谓词
- 如果operator()接受一个参数,那么叫做一元谓词
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
class GreaterTen
{
public:
bool operator()(int val)const
{
return val > 10;
}
};
void test()
{
vector<int> vec;
vec.push_back(12);
vec.push_back(18);
vec.push_back(22);
vec.push_back(8);
vec.push_back(32);
vector<int>::iterator it = find_if(vec.begin(), vec.end(), GreaterTen());
if (it == vec.end()) {
cout << "未找到" << endl;
}
else
{
cout << "找到了大于10的数字:" << *it << endl;
}
}
int main()
{
test();
system("pause");
return 0;
}
- 如果operator()接受两个参数,那么叫做二元谓词
1.3内建函数对象
1.3.1内建函数对象意义
1.概念
2.分类
3.用法
- 仿函数所产生的对象,用法和一般函数完全相同
- 使用内建函数对象,需要引入头文件
#include<functional>
1.3.2算术仿函数
1.功能描述
- 实现四则运算
- 其中negate是一元运算,其他都是二元运算
2.仿函数原型
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> modulus<T>
template<class T> negate<T>
#include<iostream>
using namespace std;
#include<functional>
void test()
{
negate<int> n;
cout << n(50) << endl;
plus<int> p;
cout << p(20, 20) << endl;
}
int main()
{
test();
system("pause");
return 0;
}
1.3.3关系仿函数
1.功能描述
2.仿函数原型
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>
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<functional>
void printVector(const vector<int>& vec)
{
for (vector<int>::const_iterator it = vec.begin();it != vec.end();it++)
{
cout << *it << " ";
}
cout << endl;
}
class MyCompare
{
public:
bool operator()(int v1, int v2)const
{
return v1 > v2;
}
};
void test()
{
vector<int> vec;
vec.push_back(12);
vec.push_back(22);
vec.push_back(8);
vec.push_back(20);
vec.push_back(15);
cout << "vector数组初始化状态" << endl;
printVector(vec);
sort(vec.begin(), vec.end());
cout << "vector数组升序排列" << endl;
printVector(vec);
sort(vec.begin(), vec.end(), greater<int>());
cout << "vector数组降序排列" << endl;
printVector(vec);
}
int main()
{
test();
system("pause");
return 0;
}
1.3.4逻辑仿函数
1.功能描述
2.函数原型
template<class T> bool logical_and<T>
template<class T> bool logical_and<T>
template<class T> bool logical_and<T>
2.STL常用算法
- 概述
- 算法主要由头文件
<algorithm>
<functional>
<numeric>
组成
2.1常用遍历算法
2.1.1概述
- 掌握常用的遍历算法
- 分类
for_each
transform
2.1.2 for_each
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
void printVector(const vector<int>& vec)
{
for (vector<int>::const_iterator it = vec.begin();it != vec.end();it++)
{
cout << *it << " ";
}
cout << endl;
}
void compareVec(int vec)
{
cout << vec << " ";
}
class compareVect
{
public:
void operator()(int val)
{
cout << val << " ";
}
};
void test()
{
vector<int> vec;
vec.push_back(10);
vec.push_back(50);
vec.push_back(8);
vec.push_back(23);
cout << "普通遍历" << endl;
printVector(vec);
cout << "for_each遍历" << endl;
for_each(vec.begin(), vec.end(), compareVec);
cout << endl;
for_each(vec.begin(), vec.end(), compareVect());
cout << endl;
}
int main()
{
test();
system("pause");
return 0;
}
2.1.3 transform
#include<iostream>
using namespace std;
#include<vector>
#include<cstdlib>
#include<algorithm>
class printVec
{
public:
void operator()(int val)
{
cout << val << " ";
}
};
class TransfVector
{
public:
int operator()(int val)
{
return val;
}
};
void test()
{
vector<int> vec;
for (int i = 1;i <= 10;i++)
{
vec.push_back(i+(rand() % 100));
}
for_each(vec.begin(), vec.end(), printVec());
cout << endl;
vector<int> vecT;
vecT.resize(vec.size());
transform(vec.begin(), vec.end(), vecT.begin(), TransfVector());
for_each(vecT.begin(), vecT.end(), printVec());
cout << endl;
}
int main()
{
test();
system("pause");
return 0;
}
2.2常用查找算法
2.2.1概括
1. 算法分类
find
find_if
adjacent_find
binary_search
count
count_if
2.2.2 find
- 查找指定元素,找到返回指定元素的迭代器,找不到返回结束迭代器end()
- 函数原型
- 按值查找元素,找到返回指定位置的迭代器,找不到返回结束迭代器位置
- beg 开始迭代器
- end 结束迭代器
- value 查找的元素
- 注意自定义数据,需要重载操作符==
#include<iostream>
using namespace std;
#include<vector>
#include<cstdlib>
#include<string>
class Person
{
public:
Person(string name,int age)
{
this->m_Name = name;
this->m_Age = age;
}
bool operator==(const Person &person)
{
if (this->m_Name == person.m_Name && this->m_Age == person.m_Age)
{
return true;
}
else
{
return false;
}
}
string m_Name;
int m_Age;
};
void test()
{
vector<int> vec;
for (int i = 1;i <= 10;i++)
{
vec.push_back(i + (rand() % 100));
}
vector<Person> vecp;
Person p1("Tom", 22);
Person p2("Jerry", 32);
Person p3("Jack", 23);
Person p4("Gost", 12);
vecp.push_back(p1);
vecp.push_back(p2);
vecp.push_back(p3);
vecp.push_back(p4);
vector<int>::iterator itf = find(vec.begin(),vec.end(),23);
if (itf == vec.end())
{
cout << "不存在该value值" << endl;
}
else
{
cout << "存在该值: " << *itf << endl;
}
vector<Person>::iterator itfp = find(vecp.begin(), vecp.end(), p2);
if (itfp == vecp.end())
{
cout << "不存在此人" << endl;
}
else
{
cout << "存在此人" << ",姓名:"<<itfp->m_Name << ",年龄:" << itfp->m_Age << endl;
}
}
int main()
{
test();
system("pause");
return 0;
}
2.2.3 find_if
1.功能描述
2.函数原型
- 按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置
- beg 开始迭代器
- end 结束迭代器
- _Pred函数或函数对象(谓词,返回bool类型的仿函数)
#include<iostream>
using namespace std;
#include<vector>
#include<cstdlib>
#include<string>
class Person
{
public:
Person(string name,int age)
{
this->m_Name = name;
this->m_Age = age;
}
bool operator==(const Person &person)
{
if (this->m_Name == person.m_Name && this->m_Age == person.m_Age)
{
return true;
}
else
{
return false;
}
}
string m_Name;
int m_Age;
};
class GreaterTen
{
public:
bool operator()(int val)
{
return val > 10;
}
};
class GetPersonAgeGt20
{
public:
bool operator()(Person &person)
{
return person.m_Age > 20;
}
};
void test()
{
vector<int> vec;
for (int i = 1;i <= 10;i++)
{
vec.push_back(i + (rand() % 100));
}
vector<Person> vecp;
Person p1("Tom", 22);
Person p2("Jerry", 32);
Person p3("Jack", 23);
Person p4("Gost", 12);
vecp.push_back(p1);
vecp.push_back(p2);
vecp.push_back(p3);
vecp.push_back(p4);
vector<int>::iterator itf = find(vec.begin(),vec.end(),23);
if (itf == vec.end())
{
cout << "不存在该value值" << endl;
}
else
{
cout << "存在该值: " << *itf << endl;
}
vector<Person>::iterator itfp = find(vecp.begin(), vecp.end(), p2);
if (itfp == vecp.end())
{
cout << "不存在此人" << endl;
}
else
{
cout << "存在此人" << ",姓名:"<<itfp->m_Name << ",年龄:" << itfp->m_Age << endl;
}
vector<int>::iterator itff = find_if(vec.begin(), vec.end(),GreaterTen() );
if (itff == vec.end())
{
cout << "不存在大于10的数据" << endl;
}
else
{
cout << "存在大于10的数据,该数据为:" << *itff << endl;
}
vector<Person>::iterator itffp = find_if(vecp.begin(), vecp.end(), GetPersonAgeGt20());
if (itffp == vecp.end())
{
cout << "不存在此人" << endl;
}
else
{
cout << "存在此人,姓名:" << itffp->m_Name << ",年龄:" << itffp->m_Age << endl;
}
}
int main()
{
test();
system("pause");
return 0;
}
2.2.4 adjacent_find
1.功能描述
2.2.5binary_search
1.功能描述
- 查找指定元素是否存在
- 函数原型
- 查找指定元素,找到返回true,否则返回false
- 注意,在无序序列中不可用
- beg 开始迭代器
- end 结束迭代器
- value 查找的元素
vector<int> vec;
vec.push_back(12);
vec.push_back(13);
2.2.6 count
1.功能描述
2.函数原型
- 统计元素出现次数
- beg 开始迭代器
- end 结束迭代器
- value 统计的元素
int num = count(vec.begin(), vec.end(), 45);
cout << "数据为45的元素个数为:" << num << endl;
Person person5("WTF", 23);
int nump = count(vecp.begin(), vecp.end(), person5);
cout << "和WTF年龄相同有多少:" << nump << endl;
2.2.7 count_if
1.功能描述
2.函数原型
- 按条件统计元素出现次数
- beg 开始迭代器
- end 结束迭代器
- _Pred 谓词
count_if(iterator beg,iterator end,_Pred)
#include<iostream>
using namespace std;
#include<vector>
#include<cstdlib>
#include<string>
#include<algorithm>
class Person
{
public:
Person(string name,int age)
{
this->m_Name = name;
this->m_Age = age;
}
bool operator==(const Person &person)
{
if (this->m_Name == person.m_Name && this->m_Age == person.m_Age)
{
return true;
}
else
{
return false;
}
}
string m_Name;
int m_Age;
};
class Greater30
{
public:
bool operator() (int val)
{
return val > 30;
}
};
class GetAgeGreater20
{
public:
bool operator()(const Person &person)
{
return person.m_Age > 20;
}
};
void test()
{
vector<int> vec;
for (int i = 1;i <= 10;i++)
{
vec.push_back(i + (rand() % 100));
}
vector<Person> vecp;
Person p1("Tom", 22);
Person p2("Jerry", 32);
Person p3("Jack", 23);
Person p4("Gost", 12);
vecp.push_back(p1);
vecp.push_back(p2);
vecp.push_back(p3);
vecp.push_back(p4);
int numf = count_if(vec.begin(), vec.end(), Greater30());
cout << "大于30的元素出现多少次:" << numf << endl;
int numfp = count_if(vecp.begin(), vecp.end(), GetAgeGreater20());
cout << "获取年龄大于20的人数:" << numfp << endl;
}
int main()
{
test();
system("pause");
return 0;
}
3.统计次数使用int
- 问题
编译器错误: 从’_int64’转换为’int’,可能导致数据丢失 - 解决方式
- (1)auto作为推导类型是c++ 11特性。linux出现错误,可能是Linux编译器没有它作为默认值(只需要使用 -std=c++11)
- (2)std::count的返回类型是size_t,不是int,并且size_t转换为int可能丢失数据。
2.3常用排序算法
2.3.1概述
1.算法分类
sort
random_shuffle
merge
reverse
2.3.2 sort
#include<iostream>
using namespace std;
#include<vector>
#include<cstdlib>
#include<algorithm>
#include<functional>
void printVect(int val)
{
cout << val << " ";
}
class PrintVec
{
public:
bool operator()(int v1,int v2)
{
return v1 > v2;
}
};
void test()
{
vector<int> vec;
for (int i = 1;i <= 10;i++)
{
vec.push_back(i + (rand() % 100));
}
sort(vec.begin(), vec.end());
for_each(vec.begin(), vec.end(), printVect);
cout << endl;
sort(vec.begin(), vec.end(), PrintVec());
for_each(vec.begin(), vec.end(), printVect);
cout << endl;
}
int main()
{
test();
system("pause");
return 0;
}
2.3.3 random_shuffle
1.功能描述
random_shuffle(vec.begin(), vec.end());
for_each(vec.begin(), vec.end(), printVect);
cout << endl;
}
2.3.4 merge
1.功能描述
2.函数原型
- 容器元素合并,并存储到另一个容器
- 注意: 两个容器必须是有序的
- beg1 容器1开始迭代器
- end1 容器1结束迭代器
- beg2 容器2开始迭代器
- end2 容器2结束迭代器
- dest 目标容器开始迭代器
merge(iterator beg1,iterator end1,iterator beg2,iterator end2,iterator dest)
- 注意点: 目标容器需要提前开辟容量
2.3.5 reverse
1.功能描述
2.函数原型
- 反转指定范围的元素
- beg 开始迭代器
- end 结束迭代器
reverse(iterator beg,iterator end)
reverse(vec.begin(), vec.end());
for_each(vec.begin(), vec.end(), printVect);
scout << endl;
2.4常用拷贝和替换算法
2.4.1概述
- 算法分类
copy
replace
replace_if
swap
2.4.2 copy
1.功能描述
2.函数原型
- 按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置
- beg 开始迭代器
- end 结束迭代器
- dest 目标起始迭代器
copy(iterator beg,iterator end,iterator dest)
vector<int> vecc;
vecc.resize(vec.size());
copy(vec.begin(), vec.end(), vecc.begin());
for_each(vecc.begin(), vecc.end(), printVect);
cout << endl;
2.4.3 replace
1.功能描述
2.函数原型
- 将区间内旧元素替换成 新元素
- beg 开始迭代器
- end 结束迭代器
- oldvalue 旧元素
- newvalue 新元素
replace(iterator beg,iterator end,oldvalue,new value)
replace(vecc.begin(), vecc.end(), 85, 99);
for_each(vecc.begin(), vecc.end(), printVect);
cout << endl;
2.4.4replace_if
1.功能描述
2.函数原型
- 按条件替换元素,满足条件的替换成指定元素
- beg 开始迭代器
- end 结束迭代器
- _Pred 谓词
- newValue 替换的新元素
replace_if(iterator beg,iterator end,_Pred,newValue)
class ReplaceElement
{
public:
bool operator()(int val)
{
return val > 50;
}
};
replace_if(vecc.begin(),vecc.end(),ReplaceElement(), 66);
for_each(vecc.begin(), vecc.end(), printVect);
cout << endl;
2.4.5 swap
1.功能概述
vector<int> vecs;
for (int i = 1;i <= 10;i++)
{
vecs.push_back(i + 10);
}
swap(vec, vecs);
for_each(vec.begin(), vec.end(), printVect);
cout << endl;
for_each(vecs.begin(), vecs.end(), printVect);
cout << endl;
2.5常用算术生成算法
2.5.1概述
1.注意
- 算术生成算法属于小型算法,使用时包含的头文件为
#include<numeric>
2.算法分类
accumulate
fill
2.5.2 accumulate
1.功能描述
2.函数原型
- 计算容器元素累计总和
- beg 开始迭代器
- end 结束迭代器
- value 起始值
accumulate(iterator beg,iterator end,value)
int total = accumulate(vec.begin(),vec.end(),0);
cout <<"总和:" << total << endl;
2.5.3 fill
1.功能描述
2. 函数原型
- 向容器中填充元素
- beg 开始迭代器
- end 结束迭代器
- value 填充的值
fill(iterator beg,iterator end,value)
2.6常用集合算法
2.6.1概述
1.算法分类
set_intersection
set_union
set_difference
2.5.2 set_intersection
1.功能描述
2.函数原型
- 求两个集合的交集
- 注意: 两个集合必须是有序序列
- beg1 容器1开始迭代器
- end1 容器1结束迭代器
- beg2 容器2开始迭代器
- end2 容器2结束迭代器
- dest 目标容器开始迭代器
set_intersection(iterator beg1,iterator end1,iterator beg2,iterator end2,iterator dest)
vector<int> vecd;
vecd.resize(min(vec.size(),vecs.size()));
sort(vec.begin(), vec.end());
sort(vecs.begin(), vecs.end());
for_each(vecs.begin(), vecs.end(), printVect);
cout << endl;
vector<int>::iterator desVec = set_intersection(vec.begin(),vec.end(),vecs.begin(),vecs.end(),vecd.begin());
for_each(vecd.begin(), desVec, printVect);
cout << endl;
2.5.3 set_union
1.功能描述
2. 函数原型
- 求两个容器的并集
- 注意: 两个集合必须是有序序列
- beg1 容器1开始迭代器
- end1 容器1结束迭代器
- beg2 容器2开始迭代器
- end2 容器2结束迭代器
- dest 目标容器开始迭代器
set_union(iterator beg1,iterator end1,iterator beg2,iterator end2,iterator dest)
vector<int> vecu;
vecu.resize(vecs.size()+vec.size());
vector<int>::iterator vecuEnd = set_union(vec.begin(), vec.end(), vecs.begin(), vecs.end(), vecu.begin());
for_each(vecu.begin(), vecuEnd, printVect);
cout << endl;
2.5.4 set_difference
1.功能描述
- 求两个集合的差集
- v1和v2容器,以v1容器为主体,和v2容器对比,元素不重合且v1有的元素,反之
2.函数原型
- 求两个容器的差集
- 注意: 两个集合必须是有序序列
- beg1 容器1开始迭代器
- end1 容器1结束迭代器
- beg2 容器2开始迭代器
- end2 容器2结束迭代器
- dest 目标容器开始迭代器
set_difference(iterator beg1,iterator end1,iterator beg2,iterator end2,iterator dest)
vector<int> veci;
veci.resize(max(vec.size(),vecs.size()));
vector<int>::iterator veciEnd = set_difference(vec.begin(), vec.end(), vecs.begin(), vecs.end(), veci.begin());
for_each(veci.begin(), veciEnd, printVect);
cout << endl;