STL算法和函數對象

 

STL算法和函數對象 #include<algorithm>


1. find() 在一個迭代器區間內查找一個特定元素,可以對任何類型容器的元素使用此算法。它會返回一個指示所找到元素的迭代器,或者是區間的末尾迭代器,可以查找容器中元素的一個子區間。
vector<int>::iterator it = find(myVector.begin()+1,myVector.end(),num);
2. find_if() 類似與find(),只不過它接受一些謂詞函數回調,而不是一個帶匹配的元素。
bool perfectScore(int num)
{ return (num>=100);}
vector<int>::iterator it = find(myVector.begin()+1,myVector.end(),perfectScore);
3. accumulate()  需要#include<numeric>,而不是#include<algorithm>
vector<double> nums;
…………code………..
double sum = accumulate(nums.begin(),nums,end(),0);
accumulate允許調用者指定要完成的操作
int product(int num1,int num2)
{
  return (num1*num2);
}
……….code…………..
double mult = accumulate(nums.begin(),nums.end(),1,product);
………………………….

函數對象 #include<functional>
可以在一個類中重載函數調用操作符,使得該類的對象可以用於替代函數指針,這些對象成爲函數對象。
c++中爲5個二元操作符提供了函數對象類模板:plus、minus、multiplies、divides、modulus、
與一元的negate。
plus<int> myPlus;
int res = myPlus(4,5);
如前面調用accumulate():
//double mult = accumulate(nums.begin(),nums.end(),1,product);
double mult = accumulate(nums.begin(),nums.end(),1,multiplies<int>());

C++中還提供了所有標準比較: equal_to、not_equal_to、less、greater、less_equal、greater_equal
優先隊列priority_queue中默認的比較是less,可以修改爲
//template<typename T,typename Container = vector<T>,typename Compare= less<T>>;
priority_queue<int,vector<int>,greater<int>> myQue;

C++中還爲3個邏輯操作提供了函數對象類:logical_not、logical_and、logical_or

函數對象適配器
捆綁器:
因爲find_if()函數只提供三個參數,所以第一個選出大於或等於num的數,則需要爲其提供四個參數,所以可以用捆綁器。
vector<int>::iterator it= find_if(myVector.begin(),myVector.end(),
bind2nd(greater_equal<int>(),num));
bind2nd把num作爲第二個參數捆綁至greater_equal。
把二元函數轉換成了一元函數
bind1st把一個實參綁定爲二元函數的第一個參數
去翻器:
選出第一個小於num的數
vector<int>::iterator it= find_if(myVector.begin(),myVector.end(),
not1(bind2nd(greater_equal<int>(),num)));
not1表示對一元函數進行操作。
對應的not2表示對二元函數進行操作。
調用成員函數:
如果你有一個包括對象的容器,有時可能想把一個類方法的指針作爲回調傳遞給一個算法。例如:可能想對序列中的每個string對象調用empty(),從而找到包括string的vector中的第一個空string。不過如果只是向find_if()傳遞string::empty()的一個指針,算法就沒有辦法知道它接收的是一個方法的指針,還是一個正常的函數指針或函數對象(調用一個類方法指針與調用一個常規函數指針有所不同,前者必須在一個對象的上下文中調用)。
對於上訴問題的解決:C++提供了一個mem_fun_ref()的轉換函數。
vector<string> strings;
vector<string>::const_iterator it = find_if(strings.begin(),strings.end(),
men_fun_ref(&string::empty));
如果容器中是對象的指針而不是對象本身,必須使用適配器mem_fun()來調用成員函數。
vector<string*> strings;
vector<string>::const_iterator it = find_if(strings.begin(),strings.end(),
men_fun (&string::empty));

適配實際函數:
不能對函數適配器bind1st、bind2nd、not1、not2直接使用常規的函數指針,因爲這些適配器需要其適配函數對象的特定typedef。因此,C++標準庫提供的最後一個函數適配器ptr_fun()允許將常規的函數指針已某種形式包裝,以便用於適配器。

編寫自己的函數對象:
可以編寫自己的函數對象來完成更特定的任務,而不只是預定義函數對象所提供的功能。如果想要對這些函數對象使用函數適配器,必須提供某種typedef。爲此,最簡單的方法就是從unary_function或binary_function派生你的函數對象類,究竟由哪個類派生取決於一個還是二個參數。這二個類在<functional>中定義,它們針對所提供的“函數”的參數和返回類型進行模塊化。
class myIsDigit:public unary_function<char,bool>
{
  public:
     bool operator() (char c) const
     { return (::isdigit©);}
}
vector<string*> strings;
vector<string>::const_iterator it = find_if(strings.begin(),strings.end(),
not1(myIsDigit()));
工具算法
min()、max()、swap()

非修改算法
1. 搜索算法
find()、find_if()
find_first_of()同時查找多個值中的某一個。
adjacent_find()會查找彼此相等的二個連續元素的第一個實例。
search_n()查找彼此相等的n個連續元素的第一個實例。
search()、find_end()查找與一個指定元素序列匹配的子序列,分別從給定區間的開始和結束處開始查找。
min_element()、max_element()可以找出序列中最小和最大的元素。
2. 數值處理算法
accumulate()
count()、count_if()可以用於計算容器中有給定值的元素的個數。
3. 比較算法
可以採用三種不同的方法來比較整個元素區間:equal()、mismatch()、lexicographical_compare()。
equal():如果所有位置對應元素相等,則返回true,否則爲false。
mismatch():返回的迭代器會指示各區間中對應元素中不相等的第一個元素。
lexicographical_compare():如果第一個區間中所有元素都小於第二個區間中相應的元素,或者如果第一個區間比第二個區間短,而且到第一個區間結束之前的所有元素都比第二個區間中相應的元素小,返回true。
如果相比較二個相同類型容器中的元素,可以使用operator==或operator<,而不採用上述函數,上述函數主要用於比較不同類型容器中的元素序列。
4. 運算算法
for_each():它會對給定區間的每個元素執行一個回調。回調可以按引用取參數,而且可以修改參數。
map<int,int>myMap;
……code…….
for_each(myMap.begin(),myMap.end(),&printPair());

5. 修改算法:
transform():類似於for_each(),區別在於transform()希望回調爲每個調用生成一個新元素,它會把生成的元素保存在指定的目標區間中。如果想通過轉換,將一個區間中的各個元素代之以調用回調後得到的結果,那麼源和目標區間可以是一樣的。
向一個vector中的各個元素增加100。
transform(myVector.begin(),myVector.end(),myVector.begin(),bind2nd(plus<int>(),100));

copy():將元素從一個區間複製到另一個區間。源和目標區間必須不同,但他們可以交疊。
copy(vecOne.begin(),vecOne.end(),vecTow().begin());

replace()和replace_if():會把一個區間中分別與某個值或某個謂詞匹配的元素替換爲一個新值。
replace_if(myVector.begin(),myVector.end(),bind2nd(less<int>(),0),0);

remove()和remove_if():會從一個區間中刪除某些特定的值,或某些符號謂詞的值,這些元素不會從底層容器中刪除,因爲算法只能訪問迭代器抽象,而不是訪問容器。如果要刪除,還要調用erase()。
remove_copy()和remove_cope_if(),它們不會修改源區間,而是把所有爲刪除的元素拷貝到一個不同的區間中去。

unique():會刪除重複的元素。

reverse():就地逆置。
reverse_copy():把逆置後的複製到另一個區間中去,源區間不變。

其他修改算法:iter_swap(),swap_ranges(),fill(),generate(),rotate(),next_permutation()和prev_permutation()。

6. 排序算法
大多數只對vector和deque有用,list有更高效的排序算法,關聯容器已經排好序
   sort():使用快速排序。
   stable_sort()使用歸併排序。
一旦對區間元素排了序,就可以應用binary_search()算法查找元素。
merge()函數允許將二個有序區間合併在一起,並且保持有序。

堆排序:
make_heap()在線性時間內將一個元素區間轉換成一個堆,最大元素即爲區間的第一個元素。
push_heap()新增一個元素到末尾。
pop_heap()從堆中刪除最大元素。
sort_heap()將一個對區間轉化成一個完全有序的區間。

其他排序算法:
partition()、partial_sort()、nth_element().

random_shuffle():隨機洗牌算法。

7. 集合算法
include():檢查一個有序區間中的所有元素是否都包含在另一個有序區間中,這些元素可以採用任何順序出現。
set_union():並
set_intersection():交
set_difference(): 差
set_symmetric_difference(); 對稱差(異或)

發佈了123 篇原創文章 · 獲贊 663 · 訪問量 157萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章