STL中的算法总结

stl算法大致分为4类1.非可变序列算法:对容器进行操作时不会改变容器的内容。2.可变序列算法:一般不会修改它们说操作的容器的内容。3.排序相关算法:包括排序算法和合并算法,二分查找算法以及有序序列的集合操作算法。4.通用数值算法。使用的比较少。算法包括原地形式,复制形式和判断函数参数形式。 原地形式是指算法把它对容器操作的结果存放在同一个容器,即被操作的容器中。 复制形式是指算法将操作结果复制到另外的容器中,或者复制到被操作容器的另一个不重叠的部分中。 判断函数参数形式是指以一个函数作为参数的形式,这类函数通常是以类的形式定义的函数对象,这种函数表示形式可以提高函数参数传递的效率,因为函数的传递可以在编译时进行。 1.非可变序列算法: 包括find,adjacent_find,count,for_each,mismarch,equal和search。1.1 findfind有find和find_if两种形式find的形式为: template<class _II, class _Ty> inline _II find(_II _F, _II _L, const _Ty& _V) {for (; _F != _L; ++_F)  if (*_F == _V)   break; return (_F); }find_if的形式为 template<class _II, class _Pr> inline _II find_if(_II _F, _II _L, _Pr _P) {for (; _F != _L; ++_F)  if (_P(*_F))   break; return (_F); }        查找满足条件_Pr的结果通常class _Pr的定义如下: class GreaterThan50  {   public:    bool operator()(int)const{return x>50;}  };函数的调用如下: int main(){vectro<int>vectorl;for(int i = 0; i != 13; ++i)vectorl.push_back(i*i);vector<int>::iterator where;where = find_if(vectorl.begin(),vectorl.end,GreaterThan50());return 0;}1.2 adjacent_find adjacent_find算法在序列种查找相邻且相等的两个元素,当找到这样的两个元素时,该算法返回指向两个元素中的第一个迭代器。adjacent_find有两种形式,一个是原始形式一个是断言形式原始形式: template<class _FI> inline _FI adjacent_find(_FI _F, _FI _L) {for (_FI _Fb; (_Fb = _F) != _L && ++_F != _L; )  if (*_Fb == *_F)   return (_Fb); return (_L); }断言形式: template<class _II, class _Ty> inline _CNTSIZ(_II) count(_II _F, _II _L, const _Ty& _V) {_CNTSIZ(_II) _N = 0; for (; _F != _L; ++_F)  if (*_F == _V)   ++_N; return (_N); }其中断言形式和上面定义的GreaterThan50()函数类似,不过要传递两个参数。1.3 countcount是一种非可变序列算法,其功能是在序列中查找等于某个给定值的元素个数。count有两种形式:count和count_if形式。 count的实现形式为 template<class _II, class _Ty> inline _CNTSIZ(_II) count(_II _F, _II _L, const _Ty& _V) {_CNTSIZ(_II) _N = 0; for (; _F != _L; ++_F)  if (*_F == _V)   ++_N; return (_N); } count_if的实现形式为 template<class _II, class _Pr> inline _CNTSIZ(_II) count_if(_II _F, _II _L, _Pr _P) {_CNTSIZ(_II) _N = 0; for (; _F != _L; ++_F)  if (_P(*_F))   ++_N; return (_N); }例如: int a[]={0,0,0,2,2,2,2,2,2,2} int final_count = count(&a[0],&a[9],1); final_count = count_if(&a[0],&a[9],bind2nd(not_equal_to<int>(),1));这里使用了两个模板函数bind2nd和not_equal_to<int>(),其中bind2nd是带有两个参数的绑定函数,把其参数绑定到第二个参数上,而bind1st是把其参数绑定到第一个参数上。not_equal_to<int>()是判断和指定的值是否相等,该算法的实现形式如下: template<class _Ty> struct not_equal_to : binary_function<_Ty, _Ty, bool> { bool operator()(const _Ty& _X, const _Ty& _Y) const  {return (_X != _Y); } };这两个函数都是在functional函数中定义的。1.4 for_each类属算法for_each的功能是对序列中的每个元素施加由函数f指定的操作。例如: void print_list(string s) {cout<<s<<endl; } int main() {list<string>dlist; dlist.insert(dlist.end,"Clark"); dlist.insert(dlist.end,"Rindt"); dlist.insert(dlist.end,"Senna"); for_each(dlist.begin(),dlist.end(),print_list); return 0;}函数的形式如下: template<class _II, class _Fn> inline _Fn for_each(_II _F, _II _L, _Fn _Op) {for (; _F != _L; ++_F)  _Op(*_F); return (_Op); }1.5 mismatch和equal mismatch和equal是比较容器中两个区间内的元素,这两个算法各有3个参数:first1,last1和first2.如果对于区间[first1,last1)内的所有位置first1+i,first1+i和first2+i所在的位置处的元素都相等,则equal算法返回真,否则返回假。mismatch算法的返回值是由两个迭代器first1+i和first2+i组成的一个pair,表示第一对不相等元素的位置,如果没有找到不相等的元素 ,则该算法返回last1和first2+(last1-first1). equal有两种形式,一个是重载的形式,包含4个参数,其中最后一个是断言部分: template<class _II1, class _II2> inline bool equal(_II1 _F, _II1 _L, _II2 _X) {return (mismatch(_F, _L, _X).first == _L); }  // TEMPLATE FUNCTION equal WITH PRED  template<class _II1, class _II2, class _Pr> inline bool equal(_II1 _F, _II1 _L, _II2 _X, _Pr _P) {return (mismatch(_F, _L, _X, _P).first == _L); }该函数在xutility中定义mismatch也有两种形式: template<class _II1, class _II2> inline pair<_II1, _II2> mismatch(_II1 _F, _II1 _L, _II2 _X) {for (; _F != _L && *_F == *_X; ++_F, ++_X)  ; return (pair<_II1, _II2>(_F, _X)); }  // TEMPLATE FUNCTION mismatch WITH PRED  template<class _II1, class _II2, class _Pr> inline pair<_II1, _II2> mismatch(_II1 _F, _II1 _L, _II2 _X, _Pr _P) {for (; _F != _L && _P(*_F, *_X); ++_F, ++_X)  ; return (pair<_II1, _II2>(_F, _X)); }//该函数在xutility中定义1.6 search search的功能是:给定两个迭代区间,将后一个区间内的对象作为一个子序列,并在前一个区间内查找出线给子序列的第一个位置。 通过迭代器区间[first1,last1)和[first2,last2)确定了两个序列,如果最后一个区间是前一个区间中的一个子序列,则该算法返回[first1,last1)中第一次出现的起始位置,否则返回last1. search也包括一个包含5个参数的重载版本,第5个参数是一个二元判断函数。 2.可变序列算法: 包括copy(复制),fill(填充),generate(生成),partition(分割),shuffle(混洗),remove(删除),replace(替换),reverse(倒序),swap(交换),transform(变换),unique().2.1 copy和copy_backward 类属算法copy和copy_backward的作用是将容器中的元素从一个区间复制到另一个区间。copy(first1,last1,first2)是把[first1,last1)内的元素复制到以last1开始的区间内,而copy_backward(first1,last1,last2)是把区间[first1,last1)内的元素按last1,last1-1...的顺序复制到last2,last2-1...的区域内。 copy和copy_backward的模板形式如下:template<class _II, class _OI> inline _OI copy(_II _F, _II _L, _OI _X) {for (; _F != _L; ++_X, ++_F)  *_X = *_F; return (_X); }  // TEMPLATE FUNCTION copy_backwardtemplate<class _BI1, class _BI2> inline _BI2 copy_backward(_BI1 _F, _BI1 _L, _BI2 _X) {while (_F != _L)  *--_X = *--_L; return (_X); }  //这两个函数在xutility的头文件内定义。2.2 fill fill和fill_n是把某个值复制到某一区间的所有位置中。fill(first,last,value)把value的last-first个副本放到区间[first,last)中。fill(first,n,value)把value的n个副本放到区间[first,first+n)中。 fill和fill_n的模板形式如下: template<class _FI, class _Ty> inline void fill(_FI _F, _FI _L, const _Ty& _X) {for (; _F != _L; ++_F)  *_F = _X; }   // TEMPLATE FUNCTION fill_n template<class _OI, class _Sz, class _Ty> inline void fill_n(_OI _F, _Sz _N, const _Ty& _X) {for (; 0 < _N; --_N, ++_F)  *_F = _X; }这两个函数在xutility中定义。2.3 generate generate算法的作用是连续调用gen函数(该函数是generate算法的第3个参数)last-first次,并用该函数的这些返回值来填充区间[first,last),这里假定gen是不带参数的函数。template<typename T>class calc_square{T i;public:calc_square():i(0){}T operator()(){++i;return i*i;};vector<int>vector1(10);generate(vector1.begin(),vector1.end(),calc_square<int>());}//这时vector1的值为1,4,9,9,16... generate的模板形式如下: template<class _FI, class _Gen> inline void generate(_FI _F, _FI _L, _Gen _G) {for (; _F != _L; ++_F)  *_F = _G(); } 该函数在algorithm中定义2.4 partition partition:对于给定区间[first,last)和一个一元判断函数pred,类属算法partition可以对该区间内的元素重新排列,以使所有满足判断函数pred的元素排在所有不满足pred的元素前面。该算法还有一个版本stable_partition,能保证分割后的每一组中元素的相对位置保持不变,它们的返回值都是一个迭代器,该迭代器代表第一组数据的结尾,同时也是第2组数据的开头。 例如: bool above40(int n){return n>40;} int array0[7] = {50,30,10,70,60,40,20}; int array1[7] = copy(&array0[0],&array0[7],&array1[0]); int *split = partition(&array1[0],&array1[7],above40);//最终array1的数据变为50 60 70 30 10 40 20 split = stable_partition(&array1[0],&array1[7],above40);//最终array1的数据变为50 70 60 10 30 40 202.5 random_shuffle random_shuffle的作用是:利用能够产生伪随机数的函数,对区间[first,last)中的元素混洗后重新排列。也就是对容器中的元素进行一种随机的排列。random_shuffle产生的排列结果近似与均匀分布。 例如: vector<int>vec2(10); for (int i = 0; i != 10; ++i) {  vec2[i] = i; } random_shuffle(vec2.begin(),vec2.end());//则vec2的内容为4 3 0 2 6 7 8 9 5 12.6 remove remove的作用是从一个区间中删除所有等于某个特定值的元素,该算法是稳定的,它可以保持从序列中删除元素后剩下元素之间的相对位置不变。remove操作并不改变它操作容器的大小。remove只是把序列中所有不需要删除的元素复制到一个较小的区间中,并返回该区间末尾的迭代器,在这个新的结束标志和向量末尾之间的那些元素的排列顺序是不确定的。2.7 replace replace的作用是把一个区间中所有等于某个特定值的元素用另一个值替换。2.8 reverse reverse的作用是倒转一个区间中元素的排列顺序。用来指定区间的迭代器必须是双向迭代器。2.9 rotate rotate的作用是对区间内的元素进行循环移位操作 rotate(first,mdddle,last)该函数将区间[first,last)内的元素循环左移middle-first个位置。函数返回后原来区间[middle,last)中的元素将出现在区间[first,first+k)中,其中k= last-middle;而原来在区间[first,middle)中的元素将出现在区间[first+k,last)中,rotate算法的参数必须是双向迭代器。 例如: vector<string>vector1("Software Engineering"); ratate(vector1.begin(),vector1.begin()+9,vector1.end());//vector1变为Engineering Software2.10 swap swap的作用是对两个值或者容器进行叫唤 例如: int high = 250,low = 0; swap(high,low);//则high = 0;low = 250; vector<int>vec1(100,1),vec2(200,2); swap(vec1,vec2)//则vec1为vector<int>(200,2),vec2为vector<int>(100,1);而且该函数通常是在常数时间内来完成的。2.11 swap_ranges swap_ranges的作用是交换两个区间中的值,而且这两个区间可以在不同的容器中, 例如: swap_ranges(first1,last1,first2)该函数将区间[first1,last1)和区间[first2,first2+N)中的内容相互交换,其中N=last1-first1.规定这个区间不可以重叠。2.12 transform transform的作用是将某个函数作用到某一区间内的每个元素上,并将该函数所返回的结果保存到另一个区间中,该算法的最后一个函数有两种形式:一种采用的是一元函数,作用到区间中的每个元素上,另一种采用的是二元函数,同时作用到两个区间中相互对应的元素上。例如: string& toLower(string& s) {  transform(s.begin(), s.end(), s.begin(), tolower); return s; } vector<string> svec; svec.push_back("Stanley B. Lippman"); svec.push_back("Scott Meyers"); svec.push_back("Nicolai M. Josuttis"); transform(svec.begin(), svec.end(), svec.begin(), toLower); copy(svec.begin(),svec.end(), ostream_iterator<string>(cout,"/n"));2.13 unique unique的作用是从输入序列中去掉所有相邻的重复元素。如果序列中的某个元素与其左面的相邻元素相等,则称该元素为相邻重复元素(注意:这里的相邻重复元素不是指两个相邻且相等的元素,而是指两个或两个以上相邻且相等的元素中除最左边元素以外的那些元素)。在该算法中,对于序列中若干相邻且相等的元素,将只保留其中的第1个元素,而删除后面的其它元素。unique算法并不改变它操作的容器的大小,而只是把除相邻重复元素之外的其它元素复制到一个较小的区间中,并返回同指向该区间末尾的迭代器。3.1 sort,stable_sort和partial_sort 这三个排序算法,其中sort算法用的是快排,partial_sort用的是堆排序,stable_sort采用的是稳定算法。3.2 nth_element nth_element的作用是在序列的第N个位置存放一个元素,该位置和该元素所满足的条件是:如果序列是有序的,则该元素就应处于该位置。此外,nth_element算法还对序列实现了分割,即所有第N个元素左边的元素都小于或等于。 3.3 binary_search、lower_bound、upper_bound和equal_range对这几个函数的总结如下:你想知道的                                           在无序区间   在有序区间          在set或map上     在multiset或multimap上期望值是否存在?                                       find       binary_search         count            find 期望值是否存在?如果有,第一个等于这个值的对象在哪里? find       equal_range           find             find或lower_bound 第一个不在期望值之前的对象在哪里?                     find_if    lower_bound           lower_bound      lower_bound 第一个在期望值之后的对象在哪里?                       find_if    upper_bound           upper_bound      upper_bound 有多少对象等于期望值?                                 count      equal_range+distance  count            count 等于期望值的所有对象在哪里?                          find(迭代) equal_range          equal_range      equal_range 3.4 merge merge的作用是合并两个有序区间,并把结果保存到另一个和两个输入区间均不重叠的区间中,inplace_merge算法的作用是合并两个相邻的有序区间,并用合并后的序列代替两个输入区间中原来的序列。 例如: merge:  merge(first1,last1,first2,last2,first3); inplace_merge:void main() {     const int VECTOR_SIZE = 8 ;     // Define a template class vector of int    typedef vector<int, allocator<int> > IntVector ;     //Define an iterator for template class vector of strings    typedef IntVector::iterator IntVectorIt ;     IntVector Numbers(VECTOR_SIZE) ;     IntVectorIt start, end, it ;     // Initialize vector Numbers    Numbers[0] = 4 ;    Numbers[1] = 10;    Numbers[2] = 70 ;    Numbers[3] = 10 ;    Numbers[4] = 30 ;    Numbers[5] = 69 ;    Numbers[6] = 96 ;    Numbers[7] = 100;     start = Numbers.begin() ;   // location of first                                // element of Numbers     end = Numbers.end() ;       // one past the location                                // last element of Numbers     cout << "Before calling inplace_merge/n" << endl ;     // print content of Numbers    cout << "Numbers { " ;    for(it = start; it != end; it++)        cout << *it << " " ;    cout << " }/n" << endl ;     //merge the elements of Numbers in place    inplace_merge(start, start + 3, end) ;     cout << "After calling inplace_merge/n" << endl ;     // print content of Numbers    cout << "Numbers { " ;    for(it = start; it != end; it++)        cout << *it << " " ;    cout << " }/n" << endl ; } 3.5 集合操作:includes,set_union,set_intersection,set_difference,set_symmetric_difference includes算法的作用是检查区间[first1,last1)中的元素是否包含在另一个区间[first2,last2)中,并根据结果返回一个布尔值。 set_union算法的作用是对于给定的两个代表集合的区间[first1,last1)和[first2,last2)生成这两个集合的并集其结果保存在区间[result,last)中,并返回last,即结果序列的尾后继值迭代器。 set_difference的作用是得到一个集合,该集合中的元素属于第1个区间,但不属于第2个区间。 set_intersection算法的作用是得到两个输入序列的交集。 set_symmetric_difference的作用是得到一个集合,该集合中元素仅属于两个输入序列中的一个,而不包括两个输入区间的交集中的元素。3.6 heap 堆的操作中 ,有4个操作函数:make_heap,push_heap,pop_heap,sort_heap make_heap:是对一个数组进行建堆,也就是这个数组初始化是扎乱的,经过make_heap可以产生一个堆 push_heap:这个函数是假设之前的元素满足堆的性质,然后在加入一个元素之后调整使其满足堆的性质。 pop_heap:这个函数假设已经存在一个堆,然后pop出一个元素之后使剩下的元素也满足堆的性质。 sort_heap:进行堆排序,输出有序元素: 这四个函数的关系:make_heap是一步一步调用push_heap来实现的,sort_heap是一步一步调用pop_heap来实现的。3.7 min,max,min_element,max_element min和max分布以两个元素作为参数,其返回值分别是两个元素中较小和较大的元素。min_element和max_element分别返回序列中最小和最大元素的迭代器。3.8 lexicographical_compare(词典比较) lexicographical_compare按下面的方法对两个输入序列进行比较:首先,该算法比较两个序列中对应元素e1和e2(分别来自序列1和序列2)。如果e1<e2,则算法立即返回,返回为真;如果e2<e1,则算法也立即返回,返回为假;否则继续堆下一对元素进行比较。如果已到达第1序列的末尾,但没有到达第2序列的末尾,则算法返回,返回为真,否则返回为假。3.9 next_permutation,pre_permutation next_permutation,pre_permutation是两个排列生成算法,next_permutation按词典序列将序列变换为下一个排列,pre_permutation按词典序列将序列变换为前一个排列。4 通用数值算法包括:accumulate,partial_sum,adjacent_difference和inner_product定义是在numeric头文件中4.1 accumulate accumulate的作用是计算给定区间中值的累加和。4.2 partial_sum partial_sum的作用是对给定的序列x0,x1,x2...xn-1,计算和的序列x0,x0+x1,x0+x1+x2...该算法可以把这些部分和保存在原序列中,也可以保存在另一个区间中。4.4 adajacent_difference adajacent_difference的作用是对于给定的序列x0,x1,x2...xn-1,计算序列中相邻两个元素的差序列x1-x0,x2-x1,x3-x2...xn-1 - xn-2,该算法可以把结果保存到原序列中,也可以保存在另一个序列中。4.5 inner_product inner_product的作用是计算两个输入序列的内积。上面这4个函数每一个都有一个重载的形式,可以自己定义函数。5 函数对象5.1 算术运算:包括plus,minus,multiplies,divides,modulus,negate plus接受两个类型为T的操作数,并返回他们的和。 minus接受两个类型为T的操作数,并返回他们的差。 multiplies接受两个类型为T的操作数,并返回他们的乘积。 divides接受两个类型为T的操作数,并返回他们的商。 modulus接受两个类型为T的操作数x和y,并返回x%y的结果。 negate接受类型为T的一个操作数,并返回她的相反数。5.2 比较运算 包括equal_to,not_equal_to,greater,less,greater_equal,less_equal equal_to接受类型为T的两个参数x和y,如果x==y,则返回true,否则返回false。 not_equal_to接受类型为T的两个参数x和y,如果x!=y,则返回true,否则返回false greater接受类型为T的两个参数x和y,如果x>y,则返回true,否则返回false less接受类型为T的两个参数x和y,如果x<y,则返回true,否则返回false greater_equal接受类型为T的两个参数x和y,如果x>=y,则返回true,否则返回false less_equal接受类型为T的两个参数x和y,如果x<=y,则返回true,否则返回false5.3 逻辑运算 包括 与,或,非 logical_end接受类型为T的两个参数x和y,返回逻辑“与”操作的布尔结果:x&&y logical_or接受类型为T的两个参数x和y,返回逻辑“或”操作的布尔结果:x||y logical_not接受类型为T的两个参数x,返回逻辑“非”操作的布尔结果:!x 5.4 否定适配器 包括not1和not2,分别取得一元和二元谓词,并返回它们的补数。template<typename Prediate>class unary_negate;unary_negate<Prediate>not1(const Prediate &x); not1函数接受一元谓词x作为输入,并以unary_negate的实例形式返回它的补数!x.template<typename Prediate>class unary_negate;unary_negate<Prediate>not2(const Prediate &x); 这个函数接受二元谓词x作为输入,并返回它的补数!x。5.5 绑定适配器 包括bind1st和bind2nd bind1st和bind2nd函数用于将一个二元算子(binary functor,bf)转换成一元算子(unary functor,uf)。为了达到这个目的,它们需要两个参数:要转换的bf和一个值(v)。我们在做比较的时候所写的表达式像 x > k ,x < k,这里的k是一个参数表示你程序里面的表达式要和k值去比较。上面这两个表达式对应的应该是bind2nd ,简单的理解就是把k作为比较表达式的第二个参数。如果使用bind1st则对应的表达式是 k > x,k < x,也就是把k作为比较表达式的第一个参数。大家可能会注意到这里面没有=的比较,先别着急,后面将会说道如何实现=的比较。先举两个例子看看bind1st和bind2nd的用法。 例如: int a[] = {1, 2, 100, 200};  std::vector< int> arr(a, a + 4);  // 移除所有小于100的元素 arr.erase( std::remove_if( arr.begin(),  arr.end(),     std::bind2nd( std::less< int>(), 100)), arr.end());  这里的比较表达式相当于arr.value < 100  如果用bind1st则表达的意思就恰恰相反  // 移除所有大于100的元素 arr.erase( std::remove_if( arr.begin(),  arr.end(),     std::bind1st( std::less< int>(), 100)), arr.end());  这里的表达式相当于100 < arr.value  当然为了实现删除大于100的元素你同样可以使用bind2nd  // 移除所有大于100的元素 arr.erase( std::remove_if( arr.begin(),  arr.end(),     std::bind2nd( std::greater< int>(), 100)), arr.end());  前面说道=的比较,比如说x <= k怎么实现呢,std又提供了一个好东西not1,我们可以说 !(x >  k) 和 x <= k是等价的,那么我们看看下面的表达式:  // 移除所有小于等于100的元素 arr.erase( std::remove_if( arr.begin(),  arr.end(),     std::not1(std::bind2nd( std::greater< int>(), 100))), arr.end());  说明:not1是否定返回值是单目的函数,std中还有not2它是否定返回值是双目的函数
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值