C++小點之範型演算法自定義比較函式的五種方法
阿新 • • 發佈:2019-02-18
零:使用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"} ;//長度分別為 2,7,1,8,3,2,6
int ll,hh ;
cin >> ll >> hh ; // 輸入1,6 時,num== 3 。輸入2,3,num== 0
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"} ;
// 長度分別為2,7,1,8,3,2,6
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 ;
//找到比 ll 大的第一個字串
auto p1 = find_if(v.begin(),v.end(),[ll]( const string &a ) {
return a.size() > ll ;
});
//找到比 hh 大 或者等於 的第一個字串
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 ){
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 ;//使用該名稱空間,使得書寫_1,_2,_n 時不需要書寫"std::placeholders::_1 "
std::vector<string> v{"11","2222222","3","44444444","555","66","777777"} ;//長度分別為 2,7,1,8,3,2,6
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 ;
}