零:使用STL自带的函数(less与greater)
vector<int> v{45,2,5,8454,34,68421,5,84,1,5};
sort(v.begin() ,v.end(),less<int>());
sort(v.begin() ,v.end(),greater<int>());
一:普通比较函数
假设有一个vector<<\string>>,你的任务是统计长度小于5的string的个数,如果使用count_if 函数的话,代码就是这样:
bool LengthIsLessThanFive(const string& str) {
return str.length() < 5;
}
int res=count_if(vec.begin(), vec.end(), LengthIsLessThanFive);
二:函数对象类,也就是仿函数
我们继续沿着上一题增加要求,这里我们要求字符串的长度必须在一个区间,而且这个区间人为指定 ,那么我们就可以写成这样:
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
class fun
{
public:
explicit fun(const int& l ,const int &h ):low(l),high(h) { }
bool operator()(const string &s) const {
return s.length() > low && s.length() < high ;
}
private:
const int high ;
const int low ;
};
int main(void){
std::vector<string> v{"11","2222222","3","44444444","555","66","777777"} ;
int ll,hh ;
cin >> ll >> hh ;
int num = count_if(v.begin(),v.end(),fun(ll,hh));
cout << "num ==" << num << endl ;
return 0 ;
}
这个我们来进行一点小小的总结:
***** 1.仿函数解决了一元或者二元谓词不能传入更多参数的尴尬
***** 2.能存储或者处理更多我们需要的有用信息
三:lambda (其实也是一种函数对象啦)
既然它也是一种函数对象,那么它就拥有函数对象的特征(解决了一元或者二元谓词不能传入更多参数的尴尬),这里我们还是要求字符串的长度必须在一个区间,而且这个区间人为指定,并且打印该区间内的单词 .
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
int main(void){
std::vector<string> v{"11","2222222","3","44444444","555","66","777777"} ;
stable_sort(v.begin() ,v.end() ,[](const string &a ,const string &b){
return a.size() < b.size() ;
});
for_each(v.begin(),v.end() ,[](const string &s ){
cout << s << " ";
}) ;
cout << endl ;
int ll,hh ;
cin >> ll >> hh ;
auto num = count_if(v.begin(),v.end(),[ll,hh ]( const string &a ) {
return a.size() > ll && a.size() < hh ;
});
cout << "num ==" << num << endl ;
auto p1 = find_if(v.begin(),v.end(),[ll]( const string &a ) {
return a.size() > ll ;
});
auto p2 = find_if(v.begin(),v.end(),[hh]( const string &a ) {
return a.size() >= hh ;
});
for_each(p1,p2,[](const string &s ){
cout << s << " ";
}) ;
cout << endl ;
return 0 ;
}
四:使用标准库bind函数
要求和前面一样,自己输入字符串的大小范围,找到有多少个字符串满足要求,输出即可 。
#include<iostream>
#include<vector>
#include<functional>
#include<algorithm>
using namespace std;
bool fun2(const string &s ,string::size_type l,string::size_type h,string::size_type temp){
return s.size() < h && s.size() > l ;
}
bool fun1(const string &s ,std::string::size_type l ){
return s.size() < l ;
}
int main(void) {
using namespace std::placeholders ;
std::vector<string> v{"11","2222222","3","44444444","555","66","777777"} ;
int num1= count_if(v.begin(),v.end() ,bind(fun1,_1,6 ) );
cout << num1 << endl ;
cout << "please input the length of the string's range : " ;
string::size_type ll,hh ;
cin >> ll >> hh ;
int num2= count_if(v.begin(),v.end() ,bind(fun2,_1,ll,hh,5555 ));
cout << num2 << endl ;
}
小结:
1. string::size_type 是一种无符号类型的值,并且能够存放的下任何string对象的大小,是string的size函数返回的变量 。在传参数的时候要注意,如果函数是这样子的:
bool fun2(const string &s ,
string::size_type &l,
string::size_type &h,
string::size_type &temp);
在传参数的时候就必须传入string::size_type 类型的变量,如果传入int类型就会出现比较奇葩的现象。也就是说如果有了size()函数的话就不要再使用int 了啦 !!
2.
bool fun2(const string &s ,
string::size_type temp);
count_if(v.begin(),v.end() ,bind(fun2,_1,ll,hh,5555 ));
_1 参数就是所遍历的这个vector ,后边的参数对应进行绑定即可
3. using namespace std::placeholders; 使用该命名空间,使得书写_1,_2,_n 时不需要书写”std::placeholders::_1 。也就是说_1,_2,_n 都在该命名空间之下 。
五:重载 < 运算符
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std ;
class my_class{
public:
my_class(const string &temp_name ,const int temp_value ):name(temp_name),value(temp_value){ }
bool operator<(const my_class & tt ) const {
return this->value < tt.value ;
}
string name ;
int value ;
};
int main(void){
my_class a[8]={{"赵",3},{"钱",5},{"宋",1},{"李",7},{"张",6},{"刘",9},{"王",456},{"龙",0}} ;
sort(a,a+8);
for(int i=0;i< 8 ;i++ )
cout << a[i].name << " : " << a[i].value << endl ;
return 0 ;
}
总结:
当需要自定义比较函数时,如果以后的操作比较都是固定的,就可以用重载,否则还是用普通函数,仿函数或者bind 函数 。(至于用哪个具体的还是要看个人喜好了。但我个人觉得bind更好用,你觉得呐??嘻嘻)