STL演算法和函數對象

來源:互聯網
上載者:User

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(); 對稱差(異或)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.