天天看点

C++STL之变异算法

C++STL之变异算法
C++STL之变异算法

1.复制

主要函数:

①copy

原型:template<classInIt,classOutIt>OutItcopy(InItfirst,InItlast,OutItx);  

该函数功能是“正向---正向”拷贝,把输入迭代器[first,last)间的元素依次拷贝到输出迭代器x中,并返回输出迭代器的尾指针。

②copy_backward

原型:template<classBidIt1, class BidIt2> BidIt2copy_backward(BidIt1first, BidIt1 last, BidIt2 x);  

该函数功能是“反向---反向”拷贝,把BidIt1中的(last,first]间元素依次拷贝到写双向迭代器x中,返回写功能输出迭代器的首指针。

copy简单示例

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    int a[5]={1,2,3,4,5};
    int b[5];
    vector<int>v;
    copy(a, a+5, b);
    copy(a, a+5, back_inserter(v));
    copy(a, a+5, ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    copy(b, b+5, ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    copy(v.begin(), v.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    return 0;
}
           

2.交换

主要函数

①swap

原型:template<classT>

           voidswap(T&a,T&b);

  两个相同模板参数类型变量的值互相交换。

②swap_ranges

原型:template<classFwdIt1, class FwdIt2>

          FwdIt2 swap_ranges(FwdIt1first, FwdIt1 last, FwdIt2 x);

该函数功能是:迭代器[first,last)间表示的容器A中元素依次与容器B中迭代器为x处开始的元素依次交换,并返回容器B中最后交换元素

的迭代器指针。

③iter_swap

原型:template<classFwdIt1, class FwdIt2>

           void iter_swap(FwdIt1x, FwdIt2 y);

该函数功能是:交换两个前向迭代指针指向的元素值.

交换简单示例

<span style="font-size:14px;">#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
using namespace std;
int main()
{
    int a=10;
    int b=20;
    cout<<"原始a,b:"<<endl;
    cout<<a<<"\t"<<b<<endl;
    swap(a, b);
    cout<<"交换后a,b:"<<endl;;
    cout<<a<<"\t"<<b<<endl;
    int a2[5]={1,2,3,4,5};
    int b2[5]={6,7,8,9,10};
    cout<<"原始数组a2:"<<endl;
    copy(a2, a2+5, ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    cout<<"原始数组b2:"<<endl;
    copy(b2, b2+5, ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    swap_ranges(a2, a2+5, b2);
    cout<<"交换后数组a2:"<<endl;
    copy(a2, a2+5, ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    cout<<"交换后数组b2:"<<endl;
    copy(b2, b2+5, ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    
    int a3[6]={10,20,30,40,50,60};
    int b3[5]={15,25,35,45,55};
    vector<int>v1(a3,a3+6);
    vector<int>v2(b3,b3+5);
    cout<<"原始v1:"<<endl;
    copy(v1.begin(), v1.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    cout<<"原始v2:"<<endl;
    copy(v2.begin(), v2.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    swap(v1,v2);
 //   iter_swap(v1.begin(), v2.begin());
    cout<<"交换后v1:"<<endl;
    copy(v1.begin(), v1.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    cout<<"交换后v2:"<<endl;
    copy(v2.begin(), v2.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    return 0;
}</span>
           

通过swap函数原型swap(T&a, T& b)可明确看出它相当于引用调用,其余两个函数swap_ranges、iter_swap相当于地址指针调用。因此示例中:基本数据类型swap(a,b)可以用iter_swap(&a,&b)代替;基本序列容器swap(v1,v2)可以用iter_swap(&v1,&v2)代替,当然从功能上说也可用swap_ranges(v1.begin(),v1.end(), v2.begin())代替;但是对数组来说只能用swap_ranges,如示例那样。因此可以总结出:对于基本数据类型可用swap或iter_swap,对数组只能用swap_ranges,对基本序列容器三个函数均可。 3.变换

主要函数

①transform

原型:template<classInIt,classOutIt,classUnop>

      OutIttransform(InItfirst,InItlast,OutItx,Unopuop);

            template<class InIt1, classInIt2, classOutIt,classBinop>

      OutIttransform(InIt1first1, InIt1 last1, InIt2 first2,OutIt x, Binopbop);

第一个模板函数功能是:一个输入迭代器容器每个元素依次做为一元函数uop参数传入并执行,结果输出到输出迭代器x表示的容器

中。即:*(x+N)=uop(*(first+N))。

第二个模板函数功能是:两个输入迭代器容器对应的一对元素做为二元函数bop参数传入并执行,结果输出到输出迭代器x表示的容器

中。即:*(x+N)=bop(*(first1+N),*(first2+N))。

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <functional>
using namespace std;
int func1(int value)
{
    return value*2;
}
int func2(int vlaue1,int value2)
{
    return vlaue1+value2;
}
int main()
{
    int a[5]={1,2,3,4,5};
    vector<int>v1(a,a+5);
    vector<int>v2(5);
    vector<int>v3;
    copy(a, a+5, ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    transform(v1.begin(), v1.end(), v1.begin(), func1);
  //  transform(v1.begin(), v1.end(), v1.begin(), bind2nd(multiplies<int>(),2));
    copy(v1.begin(), v1.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    transform(v1.begin(), v1.end(), v2.begin(), func1);
    copy(v2.begin(), v2.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    transform(v1.begin(), v1.end(), back_inserter(v3),func1);
    copy(v3.begin(), v3.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    
    int a2[5]={1,2,3,4,5};
    int b2[5]={6,7,8,9,10};
    int c2[5];
    copy(a2, a2+5, ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    copy(b2, b2+5, ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    transform(a2, a2+5, b2, c2,func2);
   // transform(a2, a2+5, b2, c2,plus<int>());
    copy(c2, c2+5, ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    return 0;
    
}
           

4.替换

主要函数

①replace

原型:template<caassFwdIt,class T>     

           void replace(FwdItfirst,FwdItlast,constT&vold,constT&vnew);

该函数功能是:遍历容器序列,若某元素等于旧值,则用新值代替。即: if(*(first+N)==vold)  *(first+N)=vnew

②replace_if

原型:template<classFwdIt,classPred,class T>     

           void replace_if(FwdItfirst,FwdItlast,Predpr,constT&val);

该函数功能是:if(pr(*(first+N)))  *(first+N)=val;

③replace_copy

原型:template<classInIt,classOutIt,class T>   

        OutItreplace_copy(InItfirst,InItlast,OutItx,constT&vold,constT&vnew);

该函数功能是:

         if (*(first + N) == vold)    *(x + N) =vnew; 

         else    *(x + N) = *(first + N)

 ④replace_copy_if

原型:template<classInIt,classOutIt,classPred,class T>    

          OutItreplace_copy_if(InItfirst,InItlast,OutItx,Predpr,constT&val);

该函数功能是:

          if (pr(*(first+ N)))   *(x + N) =val; 

          else    *(x + N) = *(first + N) 

4个replace函数简单示例

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <functional>
using namespace std;
int main()
{
    int a[9]={1,2,3,4,5,4,3,2,1};
    cout<<"原始数据:"<<endl;
    copy(a, a+9, ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    cout<<"原数据2用10代替:"<<endl;
    vector<int>v1(a,a+9);
    replace(v1.begin(), v1.end(), 2, 10);
    //replace(a, a+9, 2, 10);
    
    copy(v1.begin(), v1.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    cout<<"原始数据<4的用20代替:"<<endl;
    vector<int>v2(a,a+9);
    replace_if(v2.begin(), v2.end(), bind2nd(less<int>(), 4), 20);
    copy(v2.begin(), v2.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    
    cout<<"原始数据4用30代替:"<<endl;
    vector<int>v3(a,a+9);
    vector<int>v4;
    replace_copy(v3.begin(), v3.end(), back_inserter(v4), 4, 30);
    copy(v4.begin(), v4.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    
    cout<<"原始数据<4用40代替:"<<endl;
    vector<int>v5(a,a+9);
    vector<int>v6;
    replace_copy_if(v5.begin(), v5.end(), back_inserter(v6), bind2nd(less<int>(), 4), 40);
    copy(v6.begin(), v6.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    return 0;
}
           

一个replace易犯错误示例

#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
    int a[]={2,1,3,2,2,5};
    replace(a, a+6, a[0], 10);
    copy(a, a+6, ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    return 0;
}
           

分析:void replace(FwdItfirst, FwdItlast,constT& vold,constT& vnew)  vold参数是引用调用,而非传值调用。对本例而言,初始时vold=2,按表意形式相当于:replace(a,a+6, 2, 10), 但当第一次发现数组中元素2,恰好是a[0],这样a[0]就变成10。由于是引用调用,相当于vold=10,这样当继续扫描数组a时,按表意形式相当于:replace(a+1,a+6, 10, 10), 因为vold= vnew=10,所以a数组后续元素不可能再发生变化。

5.填充

主要函数

①fill

原型:template<classFwdIt,class T>    

           void fill(FwdItfirst,FwdItlast,constT& x);

该函数功能是:遍历容器中所有元素,每个元素都赋成值x。即:

  *(first+ N)=x

②fill_n

原型:template<classOutIt,class Size, class T>    

           void fill_n(OutItfirst, Size n, constT& x);

该函数功能是:遍历容器Size个元素,每个元素都赋成值x。即:

  *(first+ N)=x

fill函数简单示例

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
using namespace std;
int main()
{
    int a[5];
    fill(a, a+5, 0);
    copy(a, a+5, ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    
    vector<int>v1(5);
    fill(v1.begin(), v1.end(),10);
    copy(v1.begin(), v1.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    
    vector<int>v2;
    fill_n(back_inserter(v2),5,20);
    copy(v2.begin(), v2.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    return 0;
    
}
           

6.生成

主要函数

①generate

原型:template<classFwdIt,class Gen>    

         void generate(FwdItfirst,FwdItlast, Gen g);

该函数功能是:*(first+ N)=g()。

②generate_n

原型:template<classOutIt,classPred,class Gen>     

           void generate_n(OutItfirst,Distn, Gen g);

该函数功能是:*(first + N)=g();  N。

生成斐波拉契数列

<span style="font-size:14px;">#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Fibonacci
{
    int f1;
    int f2;
public:
    Fibonacci(int start1,int start2):f1(start1),f2(start2){}
    int operator()()
    {
        int r=f1+f2;
        f1=f2;
        f2=r;
        return r;
    }
};
int main()
{
    vector<int>v1(10);
    generate(v1.begin(), v1.end(), Fibonacci(0,1));
    copy(v1.begin(), v1.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    vector<int>v(20);
    generate(v.begin(), v.end(), Fibonacci(0,1));
    copy(v.begin(), v.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    cout<<*(v.begin()+9)<<endl;
    return 0;
}</span>
           

7.删除

主要函数

①remove

原型:template<classFwdIt,class T>     

          FwdItremove(FwdItfirst,FwdItlast,constT&val);

该函数功能是:首先设变量X= first,最终返回值是X。 

          if (!(*(first + N) == val))*X++ = *(first + N);

②remove_if

原型:template<classFwdIt,classPred>    

            FwdItremove_if(FwdItfirst,FwdItlast,Predpr);

该函数功能是:首先设变量X= first,最终返回值是X。 

          if (!pr(*(first+ N)))   *X++ = *(first + N); 

③remove_copy

原型:template<classInIt,classOutIt,class T>   

         OutItremove_copy(InItfirst,InItlast,OutItx,constT&val);

该函数功能是:

         if (!(*(first + N) == val))    *x++ = *(first + N);

④remove_copy_if

原型:template<classInIt,classOutIt,classPred>     

         OutItremove_copy_if(InItfirst,InItlast,OutItx,Predpr);

该函数功能是:

         if (!pr(*(first+ N)))   *x++ = *(first + N); 

remove简单示例

<span style="font-size:14px;">#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;
int main()
{
    int a[]={1,2,2,4,5,4,3,2,1};
    vector<int>v(a,a+9);
    sort(v.begin(), v.end());
    copy(v.begin(), v.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    vector<int>::iterator first=v.begin();
    vector<int>::iterator last;
    last=remove(v.begin(),v.end(),2);
    copy(v.begin(), v.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    copy(v.begin(), last, ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    return 0;
}</span>
           

remove_copy简单示例

#include <iostream>
#include <vector>
#include <fstream>
#include <iterator>
#include <functional>
#include <algorithm>
using namespace std;
int main()
{
    int a[]={1,2,3,4,5};
    copy(a, a+5, ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    vector<int>v(a,a+5);
    vector<int>::iterator first=v.begin();
    vector<int>::iterator last=remove_copy(v.begin(), v.end(), v.begin(), 3);
    copy(first, last, ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    
    vector<int>v1(a,a+5);
    vector<int>v2;
  //  ofstream out("1.txt");
    remove_copy(v1.begin(), v1.end(), back_inserter(v2), 3);
    copy(v2.begin(), v2.end(), ostream_iterator<int>(cout,"\t"));
  //  remove_copy(v2.begin(), v2.end(),ostream_iterator<int>(out,"\t"),1);
  //  out.close();
    cout<<endl;
    return 0;
}
           

已知学生信息包含姓名、学号、语文及数学成绩,从学生集合中提取总成绩大于等于150分的学生信息并按文本格式存入文件中。

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <algorithm>
#include <functional>
using namespace std;
class Student
{
public:
    string name;
    string NO;
    int chinese;
    int math;
public:
    Student(){}
    Student(string nam,string NO,int c,int m):name(nam),NO(NO),chinese(c),math(m){}
    bool operator<(const int &total)const
    {
        return (chinese+math)<total;
    }
};
bool MyCompare( const Student &s)
{
    return s<150;
}
ostream &operator<<(ostream &os,const Student &s)
{
    os<<s.name<<"\t"<<s.chinese<<"\t"<<s.math<<endl;
    return os;
}
int main()
{
    Student s1("zhang","1001",60,70);
    Student s2("zadf","1002",70,80);
    Student s3("terg","1003",75,85);
    Student s4("qzng","1004",68,78);
    Student s5("tyjh","1005",86,76);
    Student s6("plop","1006",30,80);
    
    vector<Student>v;
    v.push_back(s1);
    v.push_back(s2);
    v.push_back(s3);
    v.push_back(s4);
    v.push_back(s5);
    v.push_back(s6);
    
    vector<Student>v2;
    ofstream out("1.txt");
    vector<Student>::iterator first=v.begin();
    vector<Student>::iterator last=v.end();
    remove_copy_if(first,last,ostream_iterator<Student>(out,"\t"), MyCompare);
    copy(first,last,back_inserter(v2));
    out.close();
    copy(v2.begin(), v2.end(),ostream_iterator<Student>(cout,"\n"));
    return 0;
}
           

8.唯一

主要函数

①unique

原型:template<classFwdIt>

        FwdItunique(FwdItfirst,FwdItlast);

   template<class FwdIt,classPred>

       FwdItunique(FwdItfirst,FwdItlast,Predpr);

第1个模板函数先另X=first,返回值是X。 

  if (N == 0 || !(*(first + N) == V))

      V =*(first + N), *X++ = V;

第2个模板函数先另X=first,返回值是X,与前一模板函数功能相近,只不过调用了一元判定函数。

  if (N == 0 || !(pr(*(first+ N)) == V)) 

      V =*(first + N), *X++ = V;

②unique_copy

原型:template<classInIt,classOutIt>

    OutItunique_copy(InItfirst,InItlast,OutItx);

           template<class InIt,classOutIt,classPred>

      OutItunique_copy(InItfirst,InItlast,OutItx,Predpr);

第1个模板函数:if(N == 0 || !(*(first + N) == V))

      V =*(first + N), *x++ = V;

第2个模板函数:if(N == 0 || !pr(*(first+ N), V))

      V =*(first + N), *x++ = V;

unique函数简单示例

#include <iostream>
#include <vector>
#include <functional>
#include <iterator>
#include <algorithm>
using namespace std;
int main()
{
    int a[]={1,2,2,3,4,2,2,5};
    vector<int>v(a,a+sizeof(a)/sizeof(int));
    copy(v.begin(), v.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    sort(v.begin(), v.end(), greater<int>());
    vector<int>::iterator last=unique(v.begin(), v.end());
    copy(v.begin(), last, ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    
    vector<int>v2;
    sort(a, a+sizeof(a)/sizeof(int),greater<int>());
    unique_copy(a,a+sizeof(a)/sizeof(int), back_inserter(v2));
    copy(v2.begin(), v2.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    return 0;
}
           

 9.反转

主要函数

①reverse

原型:template<classBidIt>

           voidreverse(BidItfirst,BidItlast);

该函数功能是:在内部循环调用swap函数

           swap(*(first + N), *(last - 1 - N))

②reverse_copy

原型:template<classBidIt,classOutIt>

         OutItreverse_copy(BidItfirst,BidItlast,OutItx);

该函数功能是:*(x+ N) = *(last - 1 - N),返回x+(last-first)。

反转函数简单示例

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
    int a[]={1,2,3,4,5};
    copy(a, a+sizeof(a)/sizeof(int), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    reverse(a, a+5);
    copy(a, a+sizeof(a)/sizeof(int), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    
    vector<int>v(a,a+5);
    reverse(v.begin(), v.end());
    copy(v.begin(), v.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    
    vector<int>v2;
    reverse_copy(a,a+5,back_inserter(v2));
    copy(v2.begin(), v2.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    reverse_copy(v2.begin(), v2.end(), v2.begin());
    copy(v2.begin(), v2.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    return 0;
}
           

10.划分

主要函数

①partition

原型:template<classBidIt,classPred>

         BidItpartition(BidItfirst,BidItlast,Predpr);

该函数功能是:容器元素重新定位,确定位置K。当0<N<K,pr(*(first+N))是true;当K<=N<last-first,pr(*(first+N))是false。函数最终返回first+ K。

②stable_partition

原型:template<classFwdIt,classPred>

         FwdItstable_partition(FwdItfirst,FwdItlast,Predpr);

该函数功能是:与partition功能相似,只不过是稳定划分。若都满足条件,则原先在前面的元素当重新定位后仍在前面;若都不满足条件,则原先在前面的元素当重新定位后仍在前面。

划分函数简单示例

#include <iostream>
#include <algorithm>
#include <vector>
#include <functional>
using namespace std;
int main()
{
    int a[]={1,7,2,5,3,4,8,2,3,6};
 //   sort(a, a+10);
    vector<int>v(a,a+10);
    copy(v.begin(), v.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    cout<<"按<4划分(partition):"<<endl;
    partition(v.begin(), v.end(),bind2nd(less<int>(),4));
    copy(v.begin(), v.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    cout<<"按4划分(stable_partition):"<<endl;
    stable_partition(v.begin(), v.end(), bind2nd(less<int>(),4));
    copy(v.begin(), v.end(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    return 0;
}
           

已知学生信息包含姓名和成绩两项,把学生集合中成绩小于75分的放在容器的前面。

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <functional>
using namespace std;
struct Student
{
    char name[20];
    int grade;
};
bool GradeCmp(Student &s)
{
    return s.grade<75;
}
ostream &operator<<(ostream &os,const Student &s)
{
    os<<"("<<s.name<<"\t"<<s.grade<<")";
    return os;
}
int main()
{
    Student s[]={{"li1",79},{"li2",70},{"li3",68},{"li4",78},{"li5",65}};
    copy(s, s+5, ostream_iterator<Student>(cout,"\t"));
    cout<<endl;
    vector<Student>v(s,s+5);
    cout<<"不稳定划分(partition):"<<endl;
    partition(v.begin(), v.end(),GradeCmp);
    copy(v.begin(), v.end(), ostream_iterator<Student>(cout,"\t"));
    cout<<endl;
    
    cout<<"稳定划分(stable_partition):"<<endl;
    vector<Student>v1(s,s+5);
    stable_partition(v1.begin(), v1.end(),GradeCmp);
    copy(v1.begin(), v1.end(), ostream_iterator<Student>(cout,"\t"));
    cout<<endl;
    return 0;
    
}
           

list容器划分

#include <iostream>
#include <list>
#include <algorithm>
#include <functional>
using namespace std;
int main()
{
    int a[]={1,7,3,6,4,10,9,5,2,8};
    list<int>v(a,a+10);
    list<int>v2;
    copy(v.begin(), v.end(),front_inserter(v2));
    list<int>::iterator mid=stable_partition(v.begin(), v.end(),bind2nd(less<int>(),4));
    copy(v.begin(), mid, ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    int n=distance(v.begin(), mid);
    cout<<n<<endl;
    
    copy(v2.rbegin(), v2.rend(), ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    return 0;
}
           

11.环移 12.随机