天天看点

C++STL之非变异算法

C++STL之非变异算法

1.循环

1.1主要函数

①for_each

原形: template<classInIt,class Fun>  Funfor_each(InItfirst,InItlast, Fun f);

打印向量中每个整型元素的立方

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
void print(int n)
{
    cout<<n*n*n<<" ";
}
int main()
{
    vector<int>Number(8);
    vector<int>::iterator it=Number.begin();
    for(int i=0;i<8;i++)
    {
        Number[i]=i+1;
    }
    while(it !=Number.end())
    {
        cout<<*it<<" ";
        it++;
    }
    cout<<endl;
    for_each(it=Number.begin(), Number.end(), print);
    cout<<endl;
    return 0;
}
           

(1)for_each函数各参数的含义。start,end表示向量的起始迭代指针、结束迭代指针,不是具体的值,比如for_each(start[0],end,PrintCube)是错误的,因为start[0]表示的是向量中第一个元素的值1。但for_each(&start[0],end,PrintCube)是正确的,因为&start[0]表示的是第一个元素的地址。

(2)PrintCube函数有且必须只有一个参数,且参数类型与向量的模板类型必须一致。

PrintCube)是错误的,因为start[0]表示的是向量中第一个元素的值1。但for_each(&start[0],end, PrintCube)是正确的,因

为&start[0]表示的是第一个元素的地址。

(2)PrintCube函数有且必须只有一个参数,且参数类型与向量的模板类型必须一致。

求整数向量的和、最大值、最小值

分析:由于必须遍历整形向量的每个元素,因此可以应用for_each函数。当然可以应用全局函数的方法完成所需功能,但更好的方法 是定义一个类。

#include <iostream>
#include <algorithm>
using namespace std;
class print
{
private:
    int sum;
    int Max;
    int Min;
    int count;
public:
    print():count(0),sum(0){}
    int GetSum()
    {
        return sum;
    }
    int GetMax()
    {
        return Max;
    }
    int GetMin()
    {
        return Min;
    }
    void operator()(int x)
    {
        if(count==0)
        {
            Max=x;
            Min=x;
        }
        else
        {
            if(Max<x)
            {
                Max=x;
            }
            if(Min>x)
            {
                Min=x;
            }
        }
        sum+=x;
        count++;
    }
};
int main()
{
    int a[]={1,4,2,8,5,7};
    const int N=sizeof(a)/sizeof(int);
    print p=for_each(a,a+N,print());
    cout<<p.GetSum()<<endl;
    cout<<p.GetMax()<<endl;
    cout<<p.GetMin()<<endl;
    return 0;
}
           

2.查询

主要函数

①find

原形:template<class InIt,class T>    InItfind(InItfirst,InItlast,constT&val);

该函数是查询[first,last)间迭代器对应的元素值是否有等于val的,若有则返回其迭代器指针,若无则返回last。可知查询元素的范围是N:[0,last-first), 由于

要判定*(first+N)==val,因此模板T对应的类必须重载运算符“operator==”。

②find_if

原型:template<classInIt,classPred> InItfind_if(InItfirst,InItlast,Predpr);

参数说明:

该函数是查询[first,last)间迭代器对应的元素*(first+i),若pr(*(first+i))返回true,则返回此时的迭代器指针,表明满足条件的元素已找到;若没有找到则返回

last。

③find_first_of

原型:

template<class FwdIt1, classFwdIt2>FwdIt1find_first_of(FwdIt1first1, FwdIt1 last1,FwdIt2 first2, FwdIt2 last2); 

template<classFwdIt1, class FwdIt2, classPred>FwdIt1find_first_of(FwdIt1first1, FwdIt1 last1,FwdIt2 first2, FwdIt2 last2,Pred pr)

第1个原型含义是:若第一个前向迭代器FwdIt1---[first1,last1)间第N个元素与第二个前向迭代器FwdIt2---[first2,last2)间某元素相等,且N最小,则返回

first1+N。表明第一个前向迭代器FwdIt1中有元素与第二个前向迭代器FwdIt2中的元素相等,否则返回last1。第2个原型与第1个类似,只不过要定义预判定函

数pr(*(first1+N),*(first2+M))。

④adjacent_find

 原型: template<classFwdIt> FwdItadjacent_find(FwdItfirst,FwdItlast);

            template<class FwdIt,class Pred>FwdItadjacent_find(FwdItfirst,FwdItlast,Predpr);

第1个原型含义是:若前向迭代器FwdIt中存在第N个元素,有*(first+N)=*(first+N+1),且N最小,则表明有两个相邻元素是相等的,返回(first+N),否则返回

last。第2个原型与第1个类似,只不过要定义预判定函数pr(*(first+N),*(first+N+1))。

⑤find_end

原型:template<class FwdIt1, class FwdIt2> FwdIt1find_end(FwdIt1first1, FwdIt1 last1,FwdIt2 first2, FwdIt2 last2);

template<class FwdIt1, class FwdIt2,class Pred>   FwdIt1find_end(FwdIt1first1, FwdIt1 last1,FwdIt2 first2, FwdIt2 last2, Predpr);

第1个原型含义是:若前向迭代器FwdIt1从第N个元素开始:*(first1+N)=*(first2+0),*(first1+N+1)=*(first2+1),*[first1+(last2-first2-1)]= *[first2+(last2-first2-

1)],且N最大,则返回(first1+N),否则返回last1。也即是:返回在FwdIt1元素中最后一次完全与FwdIt2序列元素匹配的开始位置。第2个原型与第1个类似,

只不过要定义预判定函数pr(*(first1+N+M),*(first2+N+M))。

⑥search

原型: 

template<class FwdIt1, classFwdIt2> FwdIt1search(FwdIt1 first1, FwdIt1 last1,FwdIt2  first2, FwdIt2  last2);

template<class FwdIt1, class FwdIt2,class Pred> FwdIt1search(FwdIt1  first1, FwdIt1  last1,FwdIt2 first2, FwdIt  last2,Predpr);

第1个原型含义是:若前向迭代器FwdIt1从第N个元素开始:*(first1+N)=*(first2+0),*(first1+N+1)=*(first2+1),…,*

[first1+(last2-first2-1)]= *[first2+(last2-first2-1)], 且N最小,则返回(first1+N),否则返回last2。也即是:返回

在FwdIt1元素中首次完全与FwdIt2序列元素匹配的开始位置。

第2个原型与第1个类似,只不过要定义预判定函数pr(*(first1+N+M),*(first2+M))。

⑦search_n

原型:template<class FwdIt,class Dist,class T>FwdItsearch_n(FwdItfirst,FwdItlast,Distn,constT&val); 

template<classFwdIt,classDist,class T, classPred>FwdItsearch_n(FwdItfirst,FwdItlast,Distn,constT&val,Predpr);

第1个原型含义是:在前向迭代器FwdIt中,从第N个元素开始连续的n个元素满足:*(first+N)=val,*(first+1)=val,...,*(first+N+n)= val,且N最小,则返回

*(first+N),否则返回last。   

第2个原型与第1个类似,只不过要定义预判定函数pr(*(first1+N+M),val))。

7个查询函数简单应用

#include <algorithm>
#include <iostream>
using namespace std;
bool Greater(int m)
{
    return m>4;
}
int main()
{
    int a[]={1,2,2,2,3,4,4,5,6,7,1,2,2,3};
    int Size=sizeof(a)/sizeof(int);
    cout<<"原始数组:"<<endl;
    copy(a, a+Size,ostream_iterator<int>(cout,"\t"));
    cout<<endl;
    int *p1=find(a,a+Size,3);
    if(p1!=a+Size)
    {
        cout<<"find首次等于3的位置:"<<p1-a<<"\t值:"<<*p1<<endl;
    }
    cout<<endl;
    int *p2=find_if(a,a+Size,Greater);
    if(p1!=a+Size)
    {
        cout<<"find_if首次大于4的位置:"<<p2-a<<"\t值:"<<*p2<<endl;
    }
    cout<<endl;
    int b[]={10,12,6};
    int Size2=sizeof(a)/sizeof(int);
    int *p3=find_first_of(a,a+Size,b,b+Size2);
    if(p3!=a+Size)
    {
        cout<<"find_first_of首次在a数组中发现b数组中元素的位置:"<<p3-a<<"\t值:"<<*p3<<endl;
    }
    cout<<endl;
    int *p4=adjacent_find(a,a+Size);
    if(p4!=a+Size)
    {
        cout<<"adjacent_find首次相邻元素相同位置:"<<p4-a<<"\t值:"<<*p4<<endl;
    }
    cout<<endl;
    int c[]={2,3};
    int Size3=sizeof(c)/sizeof(int);
    int *p5=find_end(a,a+Size,c,c+Size3);
    if(p5!=a+Size)
    {
        cout<<"find_end最后一次匹配c数组中元素的位置:"<<p5-a<<"\t值:"<<*p5<<endl;
    }
    cout<<endl;
    int *p6=search(a,a+Size,c,c+Size3);
    if(p6 != a+Size)
    {
        cout<<"search首次匹配c数组中元素的位置:"<<p6-a<<"\t值:"<<*p5<<endl;
    }
    int *p7=search_n(a,a+Size,3,2);
    if(p7!=a+Size)
    {
        cout<<"首次出现3个2的位置:"<<p7-a<<"\t值:"<<*p7<<endl;
    }
    cout<<endl;
    return 0;
}
           

根据学号查询学生信息,且已知学号是关键字。

#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Student
{
public:
    int NO;
    string name;
    Student(int N,string nam):NO(N),name(nam){}
    bool operator == (int NO)
    {
        return this->NO==NO;
    }
};
int main()
{
    vector<Student>v;
    Student s1(101,"张三");
    Student s2(102,"张四");
    v.push_back(s1);
    v.push_back(s2);
    
    vector<Student>::iterator begin,end,it_find;
    begin=v.begin();
    end=v.end();
    
    int FindNO=102;
    it_find=find(begin,end,FindNO);
    if(it_find!=end)
    {
        cout<<(*it_find).NO<<"\t"<<(*it_find).name<<endl;
    }
    return 0;
    
}
           

已知学生基本属性:学号(整形,关键字),姓名,成绩。现在要求编相关的功能类,能添加学生对象,并具有下列查询功能:(1)按学号查询;(2)按一组学号查询;(3)按姓名查询;(4)按成绩查询;(5)按成绩范围查询。并编制简单的测试类加以测试。

分析:

  (1)设计思想:采取基本类、集合类设计方法,在集合类中进行添加、查询功能。

  (2)实现查询功能用哪个具体查询函数呢?对于按学号查询,由于学号是关键字,因此用find函数即可;对于按一组学号查询,最好用find_first_of函数,但该函数一次只能查到一个学号的学生信息,因此一定要采用循环结构,才能完成一组学号的查询;对于按姓名查询,采用find函数。由于姓名不是关键字,因此也应该采用循环结构;对于按成绩查询,应该用find函数,由于成绩不是关键字,因此也应该采用循环结构;按成绩范围查询,应采用find_if函数,当然也是循环结构。

#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
using namespace  std;
const int NO_FIND=1;
const int GRADE_FIND=2;
class Student
{
public:
    int NO;
    string name;
    int grade;
    static int mark;
    Student(int Number,string Name,int Grade):NO(Number),name(Name),grade(Grade){}
    bool operator==(const int n)const
    {
        if(mark==NO_FIND)
        {
            return NO==n;
        }
        else
        {
            return grade==n;
        }
    }
    bool operator==(const string Name)const
    {
        return name.compare(Name)==0;
    }
};
int Student::mark=-1;
ostream &operator<<(ostream &os,const Student &s)
{
    os<<s.NO<<"\t"<<s.name<<"\t"<<s.grade<<endl;
    return os;
}
class StudentFindIF
{
private:
    int low;
    int hight;
public:
    StudentFindIF(int L,int H):low(L),hight(H){}
    bool operator()(Student &s)
    {
        return s.grade>=low&&s.grade<=hight;
    }
};
class StudentCollect
{
    vector<Student>VecStud;
public:
    bool Add(Student &s)
    {
        VecStud.push_back(s);
        return true;
    }
    bool FindByNO(int no)
    {
        Student::mark=NO_FIND;
        vector<Student>::iterator te=find(VecStud.begin(),VecStud.end(),no);
        if(te!=VecStud.end())
        {
            cout<<*te<<endl;
        }
        else
        {
            cout<<"没有"<<endl;
        }
        return true;
    }
    bool FindByNO(int no[],int n)
    {
        bool bFind=false;
        Student::mark=NO_FIND;
        vector<Student>::iterator te=find_first_of(VecStud.begin(),VecStud.end(),no,no+n);
        while(te!=VecStud.end())
        {
            bFind=true;
            cout<<*te<<endl;
            te++;
            te=find_first_of(te,VecStud.end(),no,no+n);
        }
        if(!bFind)
        {
            cout<<"没有"<<endl;
        }
        return true;
    }
    bool FindByName(string Name)
    {
        bool bFind=false;
        vector<Student>::iterator te=find(VecStud.begin(),VecStud.end(),Name);
        while(te!=VecStud.end())
        {
            bFind=true;
            cout<<*te<<endl;
            te++;
            te=find(te,VecStud.end(),Name);
        }
        if(!bFind)
        {
            cout<<"没有"<<endl;
        }
        return true;
    }
    bool FindByGrade(int Grade)
    {
        Student::mark=GRADE_FIND;
        bool bFind=false;
        vector<Student>::iterator te=find(VecStud.begin(),VecStud.end(),Grade);
        while(te!=VecStud.end())
        {
            bFind=true;
            cout<<*te<<endl;
            te++;
            te=find(te,VecStud.end(),Grade);
        }
        if(!bFind)
        {
            cout<<"没有"<<endl;
        }
        return true;
    }
    bool FindByRange(int low,int hight)
    {
        bool  bFind=false;
        StudentFindIF sf(low,hight);
        vector<Student>::iterator te=find_if(VecStud.begin(),VecStud.end(),sf);
        while (te!=VecStud.end())
        {
            bFind=true;
            cout<<*te<<endl;
            te++;
            te=find_if(te,VecStud.end(),sf);
        }
        return true;
    }
};
int main()
{
    Student s1(101,"张三",50);
    Student s2(102,"李四",70);
    Student s3(103,"张三",60);
    Student s4(104,"王五",50);
    Student s5(105,"王五",80);
    StudentCollect manage;
    manage.Add(s1);
    manage.Add(s2);
    manage.Add(s3);
    manage.Add(s4);
    manage.Add(s5);
    cout<<"按学号查询(102):"<<endl;
    manage.FindByNO(102);
    cout<<"按姓名查询(张三):"<<endl;
    manage.FindByName("张三");
    cout<<"按成绩查询:"<<endl;
    manage.FindByGrade(50);
    
    int a[]={101,105,103,107};
    cout<<"按学号组查询:"<<endl;
    manage.FindByNO(a,sizeof(a)/sizeof(int));
    cout<<"按成绩范围查询[55,70]:"<<endl;
    manage.FindByRange(55,70);
    return 0;
    
}
           

3.计数

主要函数

①count原型:template<class InIt,class T> size_tcount(InItfirst, InItlast,const T& val);

该函数返回[first, last)间的元素数目,这些元素满足*(first+i) = val;

②count_if

原型:template<class InIt,class Pred,class Dist> size_t count_if(InIt first, InIt last,Pred pr);

该函数是查询[first, last)间迭代器对应元素*(first+i)的总数,条件是pr(*(first+i))返回值是true。

3.1.求数组中有多少个0

<span style="font-size:14px;">#include <algorithm>
#include <iostream>
using namespace std;
int main()
{
    int a[]={2,0,4,6,0,3,1,-7};
    const int N=sizeof(a)/sizeof(int);
    cout<<count(a,a+N,0)<<endl;
    return 0;
}</span>
           

3.2 查询有多少个学生成绩为 80 分

#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
class Student
{
public:
    int NO;
    string name;
    int grade;
    Student(int NO,string Name,int G):NO(NO),name(Name),grade(G){}
    bool operator==(int Grade)
    {
        return grade==Grade;
    }
};
int main()
{
    vector<Student>v;
    Student s1(1000,"张三",80);
    Student s2(1001,"阿阿",85);
    Student s3(1002,"爱国",80);
    Student s4(1003,"艾丝凡",80);
    v.push_back(s1);
    v.push_back(s2);
    v.push_back(s3);
    v.push_back(s4);
    cout<<"成绩为80分得人数为:"<<count(v.begin(),v.end(),80)<<endl;
    return 0;
}
           

3.3查询有多少个学生成绩高于80分

#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>
using namespace  std;
class Student
{
public:
    int NO;
    string name;
    int grade;
    Student(int NO,string name,int Grade):NO(NO),name(name),grade(Grade){}
    Student(int Grade):grade(Grade){}
    bool operator==(int Grade)
    {
        return grade=Grade;
    }
    bool operator()(const Student &s)const
    {
        return grade<s.grade;
    }
    void print()
    {
        cout<<NO<<"\t"<<name<<"\t"<<grade<<endl;
    }
};
class MatchExpress
{
    int grade;
public:
    MatchExpress(int Grade):grade(Grade){}
    bool operator()(const Student &s)const
    {
        return s.grade>grade;
    }
};
ostream &operator<<(ostream  &os,const Student &s)
{
    os<<s.NO<<"\t"<<s.name<<"\t"<<s.grade<<endl;
    return os;
}
void print(Student &s)
{
    cout<<s.NO<<"\t"<<s.name<<"\t"<<s.grade<<endl;
}
int main()
{
    vector<Student>v;
    Student s1(1000,"张三",80);
    Student s2(1001,"阿阿",85);
    Student s3(1002,"爱国",80);
    Student s4(1003,"艾丝凡",80);
    v.push_back(s1);
    v.push_back(s2);
    v.push_back(s3);
    v.push_back(s4);
    
    copy(v.begin(),v.end(),ostream_iterator<Student>(cout,"\n"));
    cout<<endl;
    for_each(v.begin(),v.end(),print);
    cout<<"成绩高于80的人数为:"<<count_if(v.begin(),v.end(),MatchExpress(80))<<endl;
    cout<<"成绩高于80的人数为:"<<count_if(v.begin(),v.end(),Student(80))<<endl;
    
    return 0;
}
           

4.比较

①equal原型: 

template<class InIt1, classInIt2>boolequal(InIt1 first, InIt1 last, InIt2 x);

template<class InIt1, classInIt2, class Pred>boolequal(InIt1 first, InIt1 last, InIt2 x, Predpr);

第1个原型含义是:对两个输入迭代器而言,若依次有:*(first+0)=*(x+0), *(first+1)=*(x+1),…*[first+(last-first-1)] =*[x+(last-first-1)],那么这两个容器序列是

相等的。

第2个原型与第1个类似, 只不过要定义预判定函数pr(*(first1+N),*(first2+N))。

②mismatch原型:

template<class InIt1, classInIt2>pair<InIt1, InIt2>mismatch(InIt1 first, InIt1 last, InIt2 x);

template<class InIt1,class InIt2,class Pred>pair<InIt1,InIt2>mismatch(InIt1 first,InIt1 last,InIt2 x, Predpr);

第1个原型含义是:对两个迭代器而言,返回第1对元素不相等时的迭代器指针,保存在pair对象中。pair有两个成员变量:first,second,分别表示Init1及

Init2不相等时的迭代指针。

第2个原型与第1个类似, 只不过要定义预判定函数pr(*(first1+N),*(first2+M))。

4.1 比较两个整型数组是否相等

<span style="font-family:SimSun;font-size:14px;">#include <algorithm>
#include <iostream>
using namespace std;
int main()
{
    int a1[]={3,1,4,1,5,9,2};
    int a2[]={3,1,4,1,5,9,3};
    const int N=sizeof(a1)/sizeof(int);
    cout<<equal(a1,a1+N,a2)<<endl;
    return 0;
}</span>
           

4.2寻找两个整型数组元素不相等的元素值

#include <algorithm>
#include <iostream>
using namespace std;
int main()
{
    int a1[]={3,1,4,1,5,9,2};
    int a2[]={3,1,4,1,5,9,3};
    const int N=sizeof(a1)/sizeof(int);
    pair<int*, int*>result=mismatch(a1,a1+N,a2);
    cout<<*(result.first)<<"\t"<<*(result.second)<<endl;
    return 0;
}
           

4.3查询第一对成绩不相等学生的信息

#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Student
{
public:
    int NO;
    string name;
    int grade;
    Student(int NO,string name,int grade):NO(NO),name(name),grade(grade){}
    bool operator==(const Student &s)const
    {
        return this->grade==s.grade;
    }
};
int main()
{
    vector<Student>v1;
    Student s1(101,"aaa",50);
    Student s2(102,"bbb",70);
    Student s3(103,"ccc",60);
    
    v1.push_back(s1);
    v1.push_back(s2);
    v1.push_back(s3);
    vector<Student>v2;
    
    Student s4(104,"ddd",50);
    Student s5(105,"eee",80);
    Student s6(106,"fff",60);
    v2.push_back(s4);
    v2.push_back(s5);
    v2.push_back(s6);
    pair<Student*, Student*> result=mismatch(v1.begin(),v1.end(),v2.begin());   //这里行不通 ?
    Student &stu1=*result.first;
    Student &stu2=*result.second;
    cout<<stu1.NO<<"\t"<<stu1.name<<"\t"<<stu1.grade<<endl;
    cout<<stu2.NO<<"\t"<<stu2.name<<"\t"<<stu2.grade<<endl;
    return 0;
}