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中的元素相等,否則返回last12個原型與第1個類似,只不過要定義預判定函


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


④adjacent_find

 原型: template<classFwdItFwdItadjacent_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;
}




注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com