1.定義算法
泛型算法是STL庫裏面定義的一些算法,這些算法能夠用一個接口操做各類數據類型,所以成爲泛型算法。大多算法定義在頭文件algorithm和numeric中。意思就是能夠用一個接口操做各類類型的算法就是泛型算法。數組
記住一些泛型算法,仍是很必要的,有時候本身寫的超長函數功能,其實調用一個庫裏面自帶的函數就解決了。less
2.一些泛型算法函數
[1]find(begin,end,value) :查找算法。begin到end是查找範圍的迭代器,value是要找的值,返回值是第一個等於給定值的迭代器,若是沒找到,則返回第二個參數表示找到告終尾。例如:spa
int target = 1;
vector<int> vec;
int array[4] = {1,2,3,4}; vec.push_back(1); vec.push_back(2); vec.push_back(3);
//查找一個vector if(find(vec.begin(), vec.end(), target) == vec.end()) printf("not find\n"); else printf("find\n"); //查找一個數組 if(find(&array[0], &array[3], target) == &ar[3]) printf("not find\n"); else printf("find\n");
find_if(begin, end, pred):查找算法。帶自定義查找函數。意思就是對begin到end上面每個元素判斷pred(*iter) == true,則表示找到返回當前迭代器,找不到則返回end。例如:code
bool isequal6(const int &v1) { return (v1 == 6); } class isequal5{ public: bool operator () (int& target) { return (target == 5); } }; class isequal{ public: isequal(int value):m_value(value){} bool operator () (int& target) { return (target == m_value); } int m_value; }; int main() { vector<int> vec1; vec1.push_back(1); vec1.push_back(5); vec1.push_back(6); if(find_if(vec1.begin(), vec1.end(), isequal6) != vec1.end()) //使用自定義函數 printf("find\n"); else printf("not find.\n"); if(find_if(vec1.begin(), vec1.end(), isequal5()) != vec1.end()) //使用仿函數 printf("find\n"); else printf("not find.\n"); if(find_if(vec1.begin(), vec1.end(), isequal(7)) != vec1.end()) //使用帶參數的構造函數仿函數 printf("find\n"); else printf("not find.\n"); return 0; }
另外說一下這個仿函數,仿函數就是讓對象擁有和函數名同樣的調用方式。上面的仿函數代碼解釋以下:對象
class isequal5{ public: bool operator () (int& target) { return (target == 5); } }; class isequal{ public: isequal(int value):m_value(value){} bool operator () (int& target) { return (target == m_value); } int m_value; }; int main() { vector<int> vec1; vec1.push_back(1); vec1.push_back(5); vec1.push_back(6); /* 此處建立了一個對象i5,以後就能夠把對象i5當成函數來使用了,例如i5(6) 由於重寫的()運算符須要傳入一個參數,因此這個i5仿函數也是須要傳入一個參數 所以下面的find_if在查找的時候對每一個iter執行了i5(*iter)操做。
也能夠用上面的例子直接建立對象:find_if(vec1.begin(), vec1.end(), isequal5()),這裏是爲了解釋,因此顯式建立了一個i5
*/ isequal5 i5; if(find_if(vec1.begin(), vec1.end(), i5) != vec1.end()) printf("find\n"); else printf("not find.\n"); /* 此處建立了一個對象is,以後就能夠把對象is當成函數來使用了,例如is(6) 所以下面的find_if在查找的時候對每一個iter執行了is(*iter)操做。 */ isequal is(7); if(find_if(vec1.begin(), vec1.end(), is) != vec1.end()) printf("find\n"); else printf("not find.\n"); return 0; }
[2]accumulate(begin,end,init_value) :求和算法。begin到end是求和範圍的迭代器,init_value是求和的初值。意思就是求前面範圍的和,最後加上init_value。blog
int total; vector<int> vec; vec.push_back(1); vec.push_back(2); vec.push_back(3); total = accumulate(vec.begin(), vec.end(), 0); printf("total:%d\n", total);
[3]equal(v1.begin,v1.end,v2.begin) :比較算法。v1.begin到v1.end是比較的範圍,v2.begin是一個迭代器的起始。若是相同則返回true,不然返回false。由於這個函數比較的時候是從範圍的開始一直比較到範圍的最後,因此第三個參數的長度應該至少等於比較的範圍的長度,不然會比較到越界。這意思就是會從vec1.begin()取值和vec2.begin()開始比較,若是vec1有8個元素,則也會從vec2的迭代器一直加8次,因此vec2至少要有8個元素。排序
vector<int> vec1; vector<int> vec2; vec1.push_back(1); vec1.push_back(2); vec2.push_back(1); vec2.push_back(2); if(equal(vec1.begin(), vec1.end(), vec2.begin())) //比較vec1是否和vec2的每一個元素是否相等(若是vec1的長度是n,則是比較vec2中的前n個) printf("equal.\n"); else printf("not equal.\n");
[4]fill(begin,end,value):填充算法。begin到end是填充的範圍,value是要填充的值。相似memset()函數。接口
fill_n(begin,size,value):也是填充算法。begin是迭代器起始位置,size是填充的長度,value是填充的值。這個就是memset()函數。
vector<int> vec1(10); vector<int>::iterator it; fill(vec1.begin(), vec1.end(), 100); //把vec1每一個元素填充爲100 for(it=vec1.begin(); it!=vec1.end(); it++) printf("%d\n", *it);
fill_n(vec1.begin(), vec1.size(), 200); //把vec1每一個元素填充爲200
[5]back_inserter():插入迭代器。這個意思就是這是一個迭代器,而且能夠插入值。給back_inserter賦值,其實就是push_back()。例如vector是空的時候,給it賦值是會core掉的(it=vec.begin();)。
vector<int> vec1; vector<int>::iterator it; //第一種賦值方式 back_inserter(vec1) = 1; back_inserter(vec1) = 2; //另一種賦值方式 back_insert_iterator<vector<int> > backiter = back_inserter(vec1); *backiter = 10; backiter++; *backiter = 20; for(it=vec1.begin(); it!=vec1.end(); it++) printf("%d\n", *it); //調用fill_n賦值 fill_n(back_inserter(vec1), 10, 100); for(it=vec1.begin(); it!=vec1.end(); it++) printf("%d\n", *it);
[6]copy(v1.begin,v1.end,v2.begin):拷貝算法。v1.begin和v1.end是拷貝源的範圍,v2.begin是拷貝目的迭代器的起始。因此v2的長度至少要等於v1的長度。這個函數的返回值是目的迭代器的尾部。爲了順序化寫代碼。
vector<int> vec1(5); vector<int> vec2(5); vector<int>::iterator it; fill_n(vec1.begin(), 5, 10); copy(vec1.begin(), vec1.end(), vec2.begin()); //把vec1的元素拷貝到vec2中 for(it=vec2.begin(); it!=vec2.end(); it++) printf("%d\n", *it);
[7]replace(begin,end,old_value,new_vlaue):替換算法。begin和end是查找的範圍,old_value要搜索的值,new_value替換的值。意思就是把begin到end範圍內的old_value替換爲new_value。
vector<int> vec1; vector<int>::iterator it; vec1.push_back(1); vec1.push_back(2); vec1.push_back(3); replace(vec1.begin(),vec1.end(), 2, 10); //把vec1中的2的替換爲10 for(it=vec1.begin(); it!=vec1.end(); it++) printf("%d\n", *it);
[8]sort(begin,end):排序算法。這個就是排序,另外能夠有第三個參數,傳入自定義的比較函數,另外也能夠傳入stl自帶的比較函數模板。
stable_sort():穩定排序算法。這個用法和上面的是同樣的。只不過這個函數對相同的元素能夠在排序好後保持以前的相對位置,這個意思就是好比排序以前的序列中a等於b,而且a在b前面,則排序好後a還在b的前面,可是用sort排序就不必定是這樣了。
bool islittle(const int &v1, const int &v2) { return (v1 < v2); } int main() { vector<int> vec1; vector<int>::iterator it, unique_end; vec1.push_back(1); vec1.push_back(2); vec1.push_back(6); vec1.push_back(3); vec1.push_back(2); sort(vec1.begin(),vec1.end()); //默認是升序排序 sort(vec1.begin(),vec1.end(), less<int>()); //升序排序 sort(vec1.begin(),vec1.end(), greater<int>()); //降序排序 sort(vec1.begin(),vec1.end(), islittle); //自定義比較函數 for(it=vec1.begin(); it!=vec1.end(); it++) printf("%d\n", *it); return 0; }
[9]unique(begin,end):去重算法。這個把begin到end之間重複的元素放到最後,返回最後一個不重複的迭代器。這個的意思就是把不重複的元素放到前面,最後的元素是什麼已經無所謂了,刪除就能夠了。
vector<int> vec1; vector<int>::iterator it, unique_end; vec1.push_back(1); vec1.push_back(2); vec1.push_back(6); vec1.push_back(3); vec1.push_back(2); sort(vec1.begin(),vec1.end()); //sort以後是{1,2,2,3,6} unique_end = unique(vec1.begin(),vec1.end()); //unique以後是{1,2,3,6,6},unique_end指向最後的6 vec1.erase(unique_end, vec1.end()); //erase以後是{1,2,3,6}