1 概述
STL算法部分主要由頭文件<algorithm>,<numeric>,<functional>組成。要使用 STL中的算法函數必須包含頭文件<algorithm>,對于數值算法須包含<numeric>,<functional>中則定義了一些模板類,用來聲明函數對象。
2 常用算法介紹
STL中算法大致分為四類:
- 非可變序列算法:指不直接修改其所操作的容器內容的算法。
- 可變序列算法:指可以修改它們所操作的容器內容的算法。
- 排序算法:包括對序列進行排序和合并的算法、搜索算法以及有序序列上的集合操作。
- 數值算法:對容器內容進行數值計算。
細致分類可分為13類,由于算法過多,所以不一一做介紹,只選取幾個最常用的算法介紹。
2.1 查找算法
查找算法共13個,包含在<algorithm>頭文件中,用來提供元素排序策略,這里只列出一部分算法:
- adjacent_find: 在iterator對標識元素范圍內,查找一對相鄰重復元素,找到則返回指向這對元素的第一個元素的ForwardIterator。否則返回last。重載版本使用輸入的二元操作符代替相等的判斷。
- count: 利用等于操作符,把標志范圍內的元素與輸入值比較,返回相等元素個數。
- count_if: 利用輸入的操作符,對標志范圍內的元素進行操作,返回結果為true的個數。
- binary_search: 在有序序列中查找value,找到返回true。重載的版本實用指定的比較函數對象或函數指針來判斷相等。
- equal_range: 功能類似equal,返回一對iterator,第一個表示lower_bound,第二個表示upper_bound。
- find: 利用底層元素的等于操作符,對指定范圍內的元素與輸入值進行比較。當匹配時,結束搜索,返回指向該元素的Iterator。
- find_if: 使用輸入的函數代替等于操作符執行find。
- search: 給出兩個范圍,返回一個ForwardIterator,查找成功指向第一個范圍內第一次出現子序列(第二個范圍)的位置,查找失敗指向last1。重載版本使用自定義的比較操作。
- search_n: 在指定范圍內查找val出現n次的子序列。重載版本使用自定義的比較操作。
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional> using namespace std;int main(int argc, char* argv[])
{int iarr[] = { 0, 1, 2, 3, 4, 5, 6, 6, 6, 7, 8 };vector<int> iv(iarr, iarr + sizeof(iarr) / sizeof(int));/*** adjacent_find: 在iterator對標識元素范圍內,查找一對相鄰重復元素 ***///原型: _FwdIt adjacent_find(_FwdIt _First, _FwdIt _Last)cout << "adjacent_find: ";cout << *adjacent_find(iv.begin(), iv.end()) << endl;/*** count: 利用等于操作符,把標志范圍內的元素與輸入值比較,返回相等元素個數。 ***///原型: count(_InIt _First, _InIt _Last, const _Ty& _Val)cout << "count(==7): ";cout << count(iv.begin(), iv.end(), 6) << endl;//統計6的個數/*** count_if: 利用輸入的操作符,對標志范圍內的元素進行操作,返回結果為true的個數。 ***///原型: count_if(_InIt _First, _InIt _Last, _Pr _Pred)//統計小于7的元素的個數 :9個cout << "count_if(<7): ";cout << count_if(iv.begin(), iv.end(), bind2nd(less<int>(), 7)) << endl;/*** binary_search: 在有序序列中查找value,找到返回true。 ***///原型: bool binary_search(_FwdIt _First, _FwdIt _Last, const _Ty& _Val)cout << "binary_search: ";cout << binary_search(iv.begin(), iv.end(), 4) << endl; //找到返回true/*** equal_range: 功能類似equal,返回一對iterator,第一個表示lower_bound,第二個表示upper_bound。 ***///原型: equal_range(_FwdIt _First, _FwdIt _Last, const _Ty& _Val)pair<vector<int>::iterator, vector<int>::iterator> pairIte; pairIte = equal_range(iv.begin(), iv.end(), 3);cout << "pairIte.first:" << *(pairIte.first) << endl;//lowerbound 3 cout << "pairIte.second:" << *(pairIte.second) << endl; //upperbound 4/*** find: 利用底層元素的等于操作符,對指定范圍內的元素與輸入值進行比較。 ***///原型: _InIt find(_InIt _First, _InIt _Last, const _Ty& _Val)cout << "find: ";cout << *find(iv.begin(), iv.end(), 4) << endl; //返回元素為4的元素的下標位置/*** find_if: 使用輸入的函數代替等于操作符執行find。 ***///原型: _InIt find_if(_InIt _First, _InIt _Last, _Pr _Pred)cout << "find_if: " << *find_if(iv.begin(), iv.end(), bind2nd(greater<int>(), 2)) << endl; //返回大于2的第一個元素的位置:3 /*** search: 給出兩個范圍,返回一個ForwardIterator,查找成功指向第一個范圍內第一次出現子序列的位置。 ***///原型: _FwdIt1 search(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2)//在iv中查找 子序列 2 3 第一次出現的位置的元素 int iarr3[3] = { 2, 3 };vector<int> iv3(iarr3, iarr3 + 2);cout << "search: " << *search(iv.begin(), iv.end(), iv3.begin(), iv3.end()) << endl;/*** search_n: 在指定范圍內查找val出現n次的子序列。 ***///原型: _FwdIt1 search_n(_FwdIt1 _First1, _FwdIt1 _Last1, _Diff2 _Count, const _Ty& _Val)//在iv中查找 2個6 出現的第一個位置的元素 cout << "search_n: " << *search_n(iv.begin(), iv.end(), 2, 6) << endl; return 0;
}/*
adjacent_find: 6
count(==7): 3
count_if(<7): 9
binary_search: 1
pairIte.first:3
pairIte.second:4
find: 4
find_if: 3
search: 2
search_n: 6
*/
2.2 排序和通用算法
排序算法共14個,包含在<algorithm>頭文件中,用來判斷容器中是否包含某個值,這里只列出一部分算法:
- merge: 合并兩個有序序列,存放到另一個序列。重載版本使用自定義的比較。
- random_shuffle: 對指定范圍內的元素隨機調整次序。重載版本輸入一個隨機數產生操作。
- nth_element: 將范圍內的序列重新排序,使所有小于第n個元素的元素都出現在它前面,而大于它的都出現在后面。重載版本使用自定義的比較操作。
- reverse: 將指定范圍內元素重新反序排序。
- sort: 以升序重新排列指定范圍內的元素。重載版本使用自定義的比較操作。
- stable_sort: 與sort類似,不過保留相等元素之間的順序關系。
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional> //定義了greater<int>()using namespace std;//要注意的技巧
template <class T>
struct display
{void operator()(const T&x) const{cout << x << " ";}
};//如果想從大到小排序,可以采用先排序后反轉的方式,也可以采用下面方法:
//自定義從大到小的比較器,用來改變排序方式
bool Comp(const int& a, const int& b) {return a > b;
}int main(int argc, char* argv[])
{int iarr1[] = { 0, 1, 2, 3, 4, 5, 6, 6, 6, 7, 8 };vector<int> iv1(iarr1, iarr1 + sizeof(iarr1) / sizeof(int));vector<int> iv2(iarr1 + 4, iarr1 + 8); //4 5 6 6vector<int> iv3(15);/*** merge: 合并兩個有序序列,存放到另一個序列 ***///iv1和iv2合并到iv3中(合并后會自動排序)merge(iv1.begin(), iv1.end(), iv2.begin(), iv2.end(), iv3.begin());cout << "merge合并后: ";for_each(iv3.begin(), iv3.end(), display<int>());cout << endl;/*** random_shuffle: 對指定范圍內的元素隨機調整次序。 ***/int iarr2[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };vector<int> iv4(iarr2, iarr2 + sizeof(iarr2) / sizeof(int));//打亂順序 random_shuffle(iv4.begin(), iv4.end());cout << "random_shuffle打亂后: ";for_each(iv4.begin(), iv4.end(), display<int>());cout << endl;/*** nth_element: 將范圍內的序列重新排序。 ***///將小于iv.begin+5的放到左邊 nth_element(iv4.begin(), iv4.begin() + 5, iv4.end());cout << "nth_element重新排序后: ";for_each(iv4.begin(), iv4.end(), display<int>());cout << endl;/*** reverse: 將指定范圍內元素重新反序排序。 ***/reverse(iv4.begin(), iv4.begin());cout << "reverse翻轉后: ";for_each(iv4.begin(), iv4.end(), display<int>());cout << endl;/*** sort: 以升序重新排列指定范圍內的元素。 ***///sort(iv4.begin(), iv4.end(), Comp); //也可以使用自定義Comp()函數sort(iv4.begin(), iv4.end(), greater<int>());cout << "sort排序(倒序): ";for_each(iv4.begin(), iv4.end(), display<int>());cout << endl;/*** stable_sort: 與sort類似,不過保留相等元素之間的順序關系。 ***/int iarr3[] = { 0, 1, 2, 3, 3, 4, 4, 5, 6 };vector<int> iv5(iarr3, iarr3 + sizeof(iarr3) / sizeof(int));stable_sort(iv5.begin(), iv5.end(), greater<int>());cout << "stable_sort排序(倒序): ";for_each(iv5.begin(), iv5.end(), display<int>());cout << endl;return 0;
}/*
merge合并后: 0 1 2 3 4 4 5 5 6 6 6 6 6 7 8
random_shuffle打亂后: 8 1 6 2 0 5 7 3 4
nth_element重新排序后: 0 1 2 3 4 5 6 7 8
reverse翻轉后: 0 1 2 3 4 5 6 7 8
sort排序(倒序): 8 7 6 5 4 3 2 1 0
stable_sort排序(倒序): 6 5 4 4 3 3 2 1 0
*/
2.3 刪除和替換算法
刪除和替換算法共15個,包含在<numeric>頭文件中,這里只列出一部分算法:
- copy: 復制序列。
- copy_backward: 與copy相同,不過元素是以相反順序被拷貝。
- remove: 刪除指定范圍內所有等于指定元素的元素。注意,該函數不是真正刪除函數。內置函數不適合使用remove和remove_if函數。
- remove_copy: 將所有不匹配元素復制到一個制定容器,返回OutputIterator指向被拷貝的末元素的下一個位置。
- remove_if: 刪除指定范圍內輸入操作結果為true的所有元素。
- remove_copy_if: 將所有不匹配元素拷貝到一個指定容器。
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional> //定義了greater<int>()using namespace std;template <class T>
struct display
{void operator()(const T&x) const{cout << x << " ";}
};int main(int argc, char* argv[])
{int iarr1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };vector<int> iv1(iarr1, iarr1 + sizeof(iarr1) / sizeof(int));vector<int> iv2(9);/*** copy: 復制序列 ***/// 原型: _OutIt copy(_InIt _First, _InIt _Last,_OutIt _Dest)copy(iv1.begin(), iv1.end(), iv2.begin());cout << "copy(iv2): ";for_each(iv2.begin(), iv2.end(), display<int>());cout << endl;/*** copy_backward: 與copy相同,不過元素是以相反順序被拷貝。 ***/// 原型: _BidIt2 copy_backward(_BidIt1 _First, _BidIt1 _Last,_BidIt2 _Dest)copy_backward(iv1.begin(), iv1.end(), iv2.rend());cout << "copy_backward(iv2): ";for_each(iv2.begin(), iv2.end(), display<int>());cout << endl;/*** remove: 刪除指定范圍內所有等于指定元素的元素。 ***/// 原型: _FwdIt remove(_FwdIt _First, _FwdIt _Last, const _Ty& _Val)remove(iv1.begin(), iv1.end(), 5); //刪除元素5cout << "remove(iv1): ";for_each(iv1.begin(), iv1.end(), display<int>());cout << endl;/*** remove_copy: 將所有不匹配元素復制到一個制定容器,返回OutputIterator指向被拷貝的末元素的下一個位置。 ***/// 原型: _OutIt remove_copy(_InIt _First, _InIt _Last,_OutIt _Dest, const _Ty& _Val)vector<int> iv3(8);remove_copy(iv1.begin(), iv1.end(), iv3.begin(), 4); //去除4 然后將一個容器的元素復制到另一個容器cout << "remove_copy(iv3): ";for_each(iv3.begin(), iv3.end(), display<int>());cout << endl;/*** remove_if: 刪除指定范圍內輸入操作結果為true的所有元素。 ***/// 原型: _FwdIt remove_if(_FwdIt _First, _FwdIt _Last, _Pr _Pred)remove_if(iv3.begin(), iv3.end(), bind2nd(less<int>(), 6)); // 將小于6的元素 "刪除"cout << "remove_if(iv3): ";for_each(iv3.begin(), iv3.end(), display<int>());cout << endl;/*** remove_copy_if: 將所有不匹配元素拷貝到一個指定容器。 ***///原型: _OutIt remove_copy_if(_InIt _First, _InIt _Last,_OutIt _Dest, _Pr _Pred)// 將iv1中小于6的元素 "刪除"后,剩下的元素再復制給iv3remove_copy_if(iv1.begin(), iv1.end(), iv2.begin(), bind2nd(less<int>(), 4));cout << "remove_if(iv2): ";for_each(iv2.begin(), iv2.end(), display<int>());cout << endl;return 0;
}/*
copy(iv2): 0 1 2 3 4 5 6 7 8
copy_backward(iv2): 8 7 6 5 4 3 2 1 0
remove(iv1): 0 1 2 3 4 6 7 8 8
remove_copy(iv3): 0 1 2 3 6 7 8 8
remove_if(iv3): 6 7 8 8 6 7 8 8
remove_if(iv2): 4 6 7 8 8 3 2 1 0
*/
對 remove_if 的擴展
#include <algorithm>
forward_iterator remove_if( forward_iterator start, forward_iterator end, Predicate p );
函數remove_if()移除序列[start, end)中所有應用于謂詞p返回true的元素。此函數返回一個指向被修剪的序列的最后一個元素迭代器。
記住, remove_if()并不會實際移除序列[start, end)中的元素;如果在一個容器上應用remove_if(), 容器的長度并不會改變(remove_if()不可能僅通過迭代器改變容器的屬性),所有的元素都還在容器里面。實際做法是,remove_if()將所有應該移除的元素都移動到了容器尾部并返回一個分界的迭代器。移除的所有元素仍然可以通過返回的迭代器訪問到。為了實際移除元素,你必須對容器自行調用erase()以擦除需要移除的元素。這也是erase-remove idiom名稱的由來:
container.erase(remove_if(container.begin(), container.end(), pred), container.end());
- replace: 將指定范圍內所有等于vold的元素都用vnew代替。
- replace_copy: 與replace類似,不過將結果寫入另一個容器。
- replace_if: 將指定范圍內所有操作結果為true的元素用新值代替。
- replace_copy_if: 與replace_if,不過將結果寫入另一個容器。
- swap: 交換存儲在兩個對象中的值。
- swap_range: 將指定范圍內的元素與另一個序列元素值進行交換。
- unique: 清除序列中重復元素,和remove類似,它也不能真正刪除元素。重載版本使用自定義比較操作。
- unique_copy: 與unique類似,不過把結果輸出到另一個容器。
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional> //定義了greater<int>()using namespace std;template <class T>
struct display
{void operator()(const T&x) const{cout << x << " ";}
};int main(int argc, char* argv[])
{int iarr[] = { 8, 10, 7, 8, 6, 6, 7, 8, 6, 7, 8 };vector<int> iv(iarr, iarr + sizeof(iarr) / sizeof(int));/*** replace: 將指定范圍內所有等于vold的元素都用vnew代替。 ***/// 原型: void replace(_FwdIt _First, _FwdIt _Last, const _Ty& _Oldval, const _Ty& _Newval)//將容器中6 替換為 3 replace(iv.begin(), iv.end(), 6, 3);cout << "replace(iv): ";for_each(iv.begin(), iv.end(), display<int>()); //由于_X是static 所以接著 增長cout << endl; //iv:8 10 7 8 3 3 7 8 3 7 8 /*** replace_copy: 與replace類似,不過將結果寫入另一個容器。 ***/// 原型: _OutIt replace_copy(_InIt _First, _InIt _Last, _OutIt _Dest, const _Ty& _Oldval, const _Ty& _Newval)vector<int> iv2(12);//將容器中3 替換為 5,并將結果寫入另一個容器。 replace_copy(iv.begin(), iv.end(), iv2.begin(), 3, 5);cout << "replace_copy(iv2): ";for_each(iv2.begin(), iv2.end(), display<int>()); cout << endl; //iv2:8 10 7 8 5 5 7 8 5 7 8 0(最后y一個殘留元素) /*** replace_if: 將指定范圍內所有操作結果為true的元素用新值代替。 ***/// 原型: void replace_if(_FwdIt _First, _FwdIt _Last, _Pr _Pred, const _Ty& _Val)//將容器中小于 5 替換為 2 replace_if(iv.begin(), iv.end(), bind2nd(less<int>(), 5), 2);cout << "replace_copy(iv): ";for_each(iv.begin(), iv.end(), display<int>()); cout << endl; //iv:8 10 7 8 2 5 7 8 2 7 8 /*** replace_copy_if: 與replace_if,不過將結果寫入另一個容器。 ***/// 原型: _OutIt replace_copy_if(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred, const _Ty& _Val)//將容器中小于 5 替換為 2,并將結果寫入另一個容器。 replace_copy_if(iv.begin(), iv.end(), iv2.begin(), bind2nd(equal_to<int>(), 8), 9);cout << "replace_copy_if(iv2): ";for_each(iv2.begin(), iv2.end(), display<int>()); cout << endl; //iv2:9 10 7 8 2 5 7 9 2 7 8 0(最后一個殘留元素)int iarr3[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, };vector<int> iv3(iarr3, iarr3 + sizeof(iarr3) / sizeof(int));int iarr4[] = { 8, 10, 7, 8, 6, 6, 7, 8, 6, };vector<int> iv4(iarr4, iarr4 + sizeof(iarr4) / sizeof(int));/*** swap: 交換存儲在兩個對象中的值。 ***/// 原型: _OutIt replace_copy_if(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred, const _Ty& _Val)//將兩個容器中的第一個元素交換 swap(*iv3.begin(), *iv4.begin());cout << "swap(iv3): ";for_each(iv3.begin(), iv3.end(), display<int>()); cout << endl;/*** swap_range: 將指定范圍內的元素與另一個序列元素值進行交換。 ***/// 原型: _FwdIt2 swap_ranges(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _Dest)//將兩個容器中的全部元素進行交換 swap_ranges(iv4.begin(), iv4.end(), iv3.begin());cout << "swap_range(iv3): ";for_each(iv3.begin(), iv3.end(), display<int>());cout << endl;/*** unique: 清除序列中相鄰的重復元素,和remove類似,它也不能真正刪除元素。 ***/// 原型: _FwdIt unique(_FwdIt _First, _FwdIt _Last, _Pr _Pred) unique(iv3.begin(), iv3.end());cout << "unique(iv3): ";for_each(iv3.begin(), iv3.end(), display<int>());cout << endl;/*** unique_copy: 與unique類似,不過把結果輸出到另一個容器。 ***/// 原型: _OutIt unique_copy(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred)unique_copy(iv3.begin(), iv3.end(), iv4.begin());cout << "unique_copy(iv4): ";for_each(iv4.begin(), iv4.end(), display<int>());cout << endl;return 0;
}/*
replace(iv): 8 10 7 8 3 3 7 8 3 7 8
replace_copy(iv2): 8 10 7 8 5 5 7 8 5 7 8 0
replace_copy(iv): 8 10 7 8 2 2 7 8 2 7 8
replace_copy_if(iv2): 9 10 7 9 2 2 7 9 2 7 9 0
swap(iv3): 8 1 2 3 4 5 6 7 8
swap_range(iv3): 0 10 7 8 6 6 7 8 6
unique(iv3): 0 10 7 8 6 7 8 6 6
unique_copy(iv4): 0 10 7 8 6 7 8 6 8
*/
2.4 排列組合算法
排列組合算法共2個,包含在<algorithm>頭文件中,用來提供計算給定集合按一定順序的所有可能排列組合,這里全部列出:
- next_permutation: 取出當前范圍內的排列,并重新排序為下一個字典序排列。重載版本使用自定義的比較操作。
- prev_permutation: 取出指定范圍內的序列并將它重新排序為上一個字典序排列。如果不存在上一個序列則返回false。重載版本使用自定義的比較操作。
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <algorithm>using namespace std;template <class T>
struct display
{void operator()(const T&x) const{cout << x << " ";}
};int main(int argc, char* argv[])
{int iarr[] = { 12, 17, 20, 22, 23, 30, 33, 40 };vector<int> iv(iarr, iarr + sizeof(iarr) / sizeof(int));/*** next_permutation: 取出當前范圍內的排列,并重新排序為下一個字典序排列。***/// 原型: bool next_permutation(_BidIt _First, _BidIt _Last)//生成下一個排列組合(字典序) next_permutation(iv.begin(), iv.end());for_each(iv.begin(), iv.end(), display<int>());cout << endl;/*** prev_permutation: 取出指定范圍內的序列并將它重新排序為上一個字典序排列。 ***/// 原型: bool prev_permutation(_BidIt _First, _BidIt _Last)prev_permutation(iv.begin(), iv.end());for_each(iv.begin(), iv.end(), display<int>());cout << endl;return 0;
}/*
12 17 20 22 23 30 40 33
12 17 20 22 23 30 33 40
*/
2.5 數值算法
數值算法共4個,包含在<numeric>頭文件中,分別是:
- accumulate: iterator對標識的序列段元素之和,加到一個由val指定的初始值上。重載版本不再做加法,而是傳進來的二元操作符被應用到元素上。
- partial_sum: 創建一個新序列,其中每個元素值代表指定范圍內該位置前所有元素之和。重載版本使用自定義操作代替加法。
- inner_product: 對兩個序列做內積(對應元素相乘,再求和)并將內積加到一個輸入的初始值上。重載版本使用用戶定義的操作。
- adjacent_difference: 創建一個新序列,新序列中每個新值代表當前元素與上一個元素的差。重載版本用指定二元操作計算相鄰元素的差。
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <numeric> //數值算法
#include <iterator> //定義了ostream_iteratorusing namespace std;int main(int argc, char* argv[])
{int arr[] = { 1, 2, 3, 4, 5 };vector<int> vec(arr, arr + 5);vector<int> vec2(arr, arr + 5);// accumulate: iterator對標識的序列段元素之和,加到一個由val指定的初始值上。int temp;int val = 0;temp = accumulate(vec.begin(), vec.end(), val);cout << "accumulate(val = 0): " << temp << endl;val = 1;temp = accumulate(vec.begin(), vec.end(), val);cout << "accumulate(val = 1): " << temp << endl;//inner_product: 對兩個序列做內積(對應元素相乘,再求和)并將內積加到一個輸入的初始值上。//這里是:1*1 + 2*2 + 3*3 + 4*4 + 5*5val = 0;temp = inner_product(vec.begin(), vec.end(), vec2.begin(), val);cout << "inner_product(val = 0): " << temp << endl;//partial_sum: 創建一個新序列,其中每個元素值代表指定范圍內該位置前所有元素之和。//第一次,1 第二次,1+2 第三次,1+2+3 第四次,1+2+3+4ostream_iterator<int> oit(cout, " "); //迭代器綁定到cout上作為輸出使用cout << "ostream_iterator: ";partial_sum(vec.begin(), vec.end(), oit);//依次輸出前n個數的和cout << endl;//第一次,1 第二次,1-2 第三次,1-2-3 第四次,1-2-3-4cout << "ostream_iterator(minus): ";partial_sum(vec.begin(), vec.end(), oit, minus<int>());//依次輸出第一個數減去(除第一個數外到當前數的和)cout << endl;//adjacent_difference: 創建一個新序列,新序列中每個新值代表當前元素與上一個元素的差。//第一次,1-0 第二次,2-1 第三次,3-2 第四次,4-3cout << "adjacent_difference: ";adjacent_difference(vec.begin(), vec.end(), oit); //輸出相鄰元素差值 后面-前面cout << endl;//第一次,1+0 第二次,2+1 第三次,3+2 第四次,4+3cout << "adjacent_difference(plus): ";adjacent_difference(vec.begin(), vec.end(), oit, plus<int>()); //輸出相鄰元素差值 后面-前面 cout << endl;return 0;
}/*
accumulate(val = 0): 15
accumulate(val = 1): 16
inner_product(val = 0): 55
ostream_iterator: 1 3 6 10 15
ostream_iterator(minus): 1 -1 -4 -8 -13
adjacent_difference: 1 1 1 1 1
adjacent_difference(plus): 1 3 5 7 9
*/
2.6 生成和異變算法
生成和異變算法共6個,包含在<algorithm>頭文件中,這里只列出一部分算法:
- fill: 將輸入值賦給標志范圍內的所有元素。
- fill_n: 將輸入值賦給first到first+n范圍內的所有元素。
- for_each: 用指定函數依次對指定范圍內所有元素進行迭代訪問,返回所指定的函數類型。該函數不得修改序列中的元素。
- generate: 連續調用輸入的函數來填充指定的范圍。
- generate_n: 與generate函數類似,填充從指定iterator開始的n個元素。
- transform: 將輸入的操作作用與指定范圍內的每個元素,并產生一個新的序列。重載版本將操作作用在一對元素上,另外一個元素來自輸入的另外一個序列。結果輸出到指定容器。
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>using namespace std;template <class T>
struct display
{void operator()(const T&x) const{cout << x << " ";}
};
// 作用類似于上面結構體,只不過只能顯示int類型的數據
void printElem(int& elem)
{cout << elem << " ";
}template<class T>
struct plus2
{void operator()(T&x)const{x += 2;}};class even_by_two
{
private:static int _x; // 注意靜態變量
public:int operator()()const{return _x += 2;}
};
int even_by_two::_x = 0; // 初始化靜態變量int main(int argc, char* argv[])
{int iarr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };vector<int> iv(iarr, iarr + sizeof(iarr) / sizeof(int));/*** fill: 將輸入值賦給標志范圍內的所有元素。 ***/// 原型: void fill(_FwdIt _First, _FwdIt _Last, const _Ty& _Val) fill(iv.begin(), iv.end(),5);cout << "fill: ";for_each(iv.begin(), iv.end(), display<int>());cout << endl;/*** fill_n: 將輸入值賦給first到first+n范圍內的所有元素。 ***/// 原型: _OutIt fill_n(_OutIt _Dest, _Diff _Count, const _Ty& _Val)fill_n(iv.begin(), 4, 3); // 賦4個3給iv cout << "fill_n: ";for_each(iv.begin(), iv.end(), display<int>());cout << endl;/*** for_each: 用指定函數依次對指定范圍內所有元素進行迭代訪問,返回所指定的函數類型。 ***/// 原型: _Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func)for_each(iv.begin(), iv.end(), plus2<int>()); // 每個元素+2cout << "for_each: ";for_each(iv.begin(), iv.end(), printElem); // 輸出cout << endl;/*** generate: 連續調用輸入的函數來填充指定的范圍。 ***/// 原型: void generate(_FwdIt _First, _FwdIt _Last, _Fn0 _Func)// 使用even_by_two()函數返回的值,來填充容器ivgenerate(iv.begin(), iv.end(), even_by_two());cout << "generate: ";for_each(iv.begin(), iv.end(), display<int>());cout << endl;/*** generate_n: 與generate函數類似,填充從指定iterator開始的n個元素。 ***/// 原型: _OutIt generate_n(_OutIt _Dest, _Diff _Count, _Fn0 _Func)// 使用even_by_two()函數返回的值,來填充容器iv的前三個值generate_n(iv.begin(), 3, even_by_two());cout << "generate_n: ";for_each(iv.begin(), iv.end(), display<int>()); // 由于_X是static 所以接著 增長cout << endl;/*** transform: 將輸入的操作作用與指定范圍內的每個元素,并產生一個新的序列。 ***/// 原型: _OutIt transform(_InIt _First, _InIt _Last, _OutIt _Dest, _Fn1 _Func)//容器的所有值全部減2transform(iv.begin(), iv.end(), iv.begin(), bind2nd(minus<int>(), 2));cout << "transform: ";for_each(iv.begin(), iv.end(), display<int>()); // 由于_X是static 所以接著 增長cout << endl;return 0;
}/*
fill: 5 5 5 5 5 5 5 5 5
fill_n: 3 3 3 3 5 5 5 5 5
for_each: 5 5 5 5 7 7 7 7 7
generate: 2 4 6 8 10 12 14 16 18
generate_n: 20 22 24 8 10 12 14 16 18
transform: 18 20 22 6 8 10 12 14 16
*/
2.7 關系算法
關系算法共8個,包含在<algorithm>頭文件中,這里只列出一部分算法:
- equal: 如果兩個序列在標志范圍內元素都相等,返回true。重載版本使用輸入的操作符代替默認的等于操作符。
- includes: 判斷第一個指定范圍內的所有元素是否都被第二個范圍包含,使用底層元素的<操作符,成功返回true。重載版本使用用戶輸入的函數。
- max: 返回兩個元素中較大一個。重載版本使用自定義比較操作。
- min: 返回兩個元素中較小一個。重載版本使用自定義比較操作。
- max_element: 返回一個ForwardIterator,指出序列中最大的元素。重載版本使用自定義比較操作。
- min_element: 返回一個ForwardIterator,指出序列中最小的元素。重載版本使用自定義比較操作。
- mismatch: 并行比較兩個序列,指出第一個不匹配的位置,返回一對iterator,標志第一個不匹配元素位置。如果都匹配,返回每個容器的last。重載版本使用自定義的比較操作。
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <algorithm>using namespace std;int main(int argc, char* argv[])
{int iarr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };vector<int> iv1(iarr, iarr + 5);vector<int> iv2(iarr, iarr + 9);// equal: 如果兩個序列在標志范圍內元素都相等,返回true。cout <<"equal: " << equal(iv1.begin(), iv1.end(), iv2.begin()) << endl;// 1 表示相等,因為只比較跟 iv1長度大小的數組 //includes: 判斷第一個指定范圍內的所有元素是否都被第二個范圍包含,使用底層元素的<操作符,成功返回true。//判斷判斷iv2中元素是否都出現在iv1中cout << "includes: " << includes(iv1.begin(), iv1.end(), iv2.begin(), iv2.end()) << endl;//max: 返回兩個元素中較大一個。cout << "max: " << max(iv1[0],iv1[1]) << endl;//min: 返回兩個元素中較小一個。cout << "min: " << min(iv1[0], iv1[1]) << endl;//max_element: 返回一個ForwardIterator,指出序列中最大的元素。cout << "max_element: " << *max_element(iv1.begin(), iv1.end()) << endl;//min_element: 返回一個ForwardIterator,指出序列中最小的元素。cout << "min_element: " << *min_element(iv1.begin(), iv1.end()) << endl;// mismatch: 并行比較兩個序列,指出第一個不匹配的位置,返回一對iterator,標志第一個不匹配元素位置。如果都匹配,返回每個容器的last。pair<vector<int>::iterator, vector<int>::iterator> pa;pa = mismatch(iv1.begin(), iv1.end(), iv2.begin());if (pa.first == iv1.end()) // true 表示相等,因為只比較跟iv1長度大小的數組 cout << "第一個向量與第二個向量匹配" << endl;else{cout << "兩個向量不同點--第一個向量點:" << *(pa.first) << endl; //這樣寫很危險,應該判斷是否到達end cout << "兩個向量不同點--第二個向量點:" << *(pa.second) << endl;}return 0;
}/*
equal: 1
includes: 0
max: 2
min: 1
max_element: 5
min_element: 1
第一個向量與第二個向量匹配
*/
2.8 集合算法
集合算法共4個,包含在<algorithm>頭文件中,這里全部列出:
- set_union: 構造一個有序序列,包含兩個序列中所有的不重復元素。重載版本使用自定義的比較操作。
- set_intersection: 構造一個有序序列,其中元素在兩個序列中都存在。重載版本使用自定義的比較操作。
- set_difference: 構造一個有序序列,該序列僅保留第一個序列中存在的而第二個中不存在的元素。重載版本使用自定義的比較操作。
- set_symmetric_difference: 構造一個有序序列,該序列取兩個序列的對稱差集(并集-交集)。
#include "stdafx.h"
#include <iostream>
#include <set>
#include <algorithm>
#include <iterator> using namespace std;template <class T>
struct display
{void operator()(const T&x) const{cout << x << " ";}
};int main(int argc, char* argv[])
{int iarr1[] = { 1, 3, 5, 7, 9, 11 };int iarr2[] = { 1, 1, 2, 3, 5, 8, 13 };multiset<int> s1(iarr1, iarr1 + 6);multiset<int> s2(iarr2, iarr2 + 7);cout << "s1: ";for_each(s1.begin(), s1.end(), display<int>());cout << endl;cout << "s2: ";for_each(s2.begin(), s2.end(), display<int>());cout << endl;/*** set_union: 構造一個有序序列,包含兩個序列中所有的不重復元素。 ***/// 原型: _OutIt set_union(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest)cout << "union of s1 and s2: ";//兩個集合合并,相同元素個數取 max(m,n)。 set_union(s1.begin(), s1.end(), s2.begin(), s2.end(), ostream_iterator<int>(cout, " "));cout << endl;/*** set_intersection: 構造一個有序序列,其中元素在兩個序列中都存在。 ***/// 原型: _OutIt set_union(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest)cout << "Intersection of s1 and s2: ";//兩個集合交集,相同元素個數取 min(m,n). set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), ostream_iterator<int>(cout, " "));cout << endl;/*** set_difference: 構造一個有序序列,該序列僅保留第一個序列中存在的而第二個中不存在的元素。 ***/// 原型: _OutIt set_union(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest)cout << "Intersection of s1 and s2: ";//兩個集合差集 就是去掉S1中 的s2 set_difference(s1.begin(), s1.end(), s2.begin(), s2.end(), ostream_iterator<int>(cout, " "));cout << endl;/*** set_symmetric_difference: 構造一個有序序列,該序列取兩個序列的對稱差集(并集-交集)。 ***/// 原型: _OutIt set_union(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest)cout << "Intersection of s1 and s2: ";//兩個集合對稱差集:就是取兩個集合互相沒有的元素 。兩個排序區間,元素相等指針后移,不等輸出小的并前進 //相同元素的個數 abs(m-n) set_symmetric_difference(s1.begin(), s1.end(), s2.begin(), s2.end(), ostream_iterator<int>(cout, " "));cout << endl;return 0;
}/*
s1: 1 3 5 7 9 11
s2: 1 1 2 3 5 8 13
union of s1 and s2: 1 1 2 3 5 7 8 9 11 13
Intersection of s1 and s2: 1 3 5
Intersection of s1 and s2: 7 9 11
Intersection of s1 and s2: 1 2 7 8 9 11 13
*/
2.9 堆算法
集合算法共4個,包含在<algorithm>頭文件中,這里只列出一部分算法:
- make_heap: 把指定范圍內的元素生成一個堆。重載版本使用自定義比較操作。
- pop_heap: 并不真正把最大元素從堆中彈出,而是重新排序堆。它把first和last-1交換,然后重新生成一個堆。可使用容器的back來訪問被"彈出"的元素或者使用pop_back進行真正的刪除。重載版本使用自定義的比較操作。
- push_heap: 假設first到last-1是一個有效堆,要被加入到堆的元素存放在位置last-1,重新生成堆。在指向該函數前,必須先把元素插入容器后。重載版本使用指定的比較操作。
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <algorithm>using namespace std;template <class T>
struct display
{void operator()(const T&x) const{cout << x << " ";}
};int main(int argc, char* argv[])
{int iarr[] = { 4, 5, 1, 3, 2 };vector<int> iv(iarr, iarr + sizeof(iarr) / sizeof(int));/*** make_heap: 把指定范圍內的元素生成一個堆。 ***/// 原型: void make_heap(_RanIt _First, _RanIt _Last)make_heap(iv.begin(), iv.end());cout << "make_heap: ";for_each(iv.begin(), iv.end(), display<int>());cout << endl;/*** pop_heap: 并不真正把最大元素從堆中彈出,而是重新排序堆。 ***/// 原型: void pop_heap(_RanIt _First, _RanIt _Last)pop_heap(iv.begin(), iv.end());iv.pop_back();cout << "pop_heap: ";for_each(iv.begin(), iv.end(), display<int>());cout << endl;/*** push_heap: 假設first到last-1是一個有效堆,要被加入到堆的元素存放在位置last-1,重新生成堆。 ***/// 原型: void push_heap(_RanIt _First, _RanIt _Last)iv.push_back(6);push_heap(iv.begin(), iv.end());cout << "push_heap: ";for_each(iv.begin(), iv.end(), display<int>());cout << endl;return 0;
}/*
make_heap: 5 4 1 3 2
pop_heap: 4 3 1 2
push_heap: 6 4 1 2 3
*/
參考:
ChenZhongzhou
yao_yao_2015
tick_tock97
轉載于:https://www.cnblogs.com/linuxAndMcu/p/10264339.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
總結
以上是生活随笔為你收集整理的[C++ STL] 常用算法总结的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。