- 循环
- 查询
- 计数
- 比较
非变异算法主要包含以下函数
序号 |
功能 |
函数名称 |
说明 |
1 |
循环 |
for_each |
遍历容器元素,对每元素执行相同的操作 |
2 |
查询 |
find |
在序列中找出某个值的第一次出现的位置 |
find_if |
在序列中找出符合某谓词的第一个元素 |
||
find_first_of |
在序列中找出第一次出现指定值集中之值的位置 |
||
adjacent_find |
在序列中找出第一次相邻值相等元素的位置 |
||
find_end |
在序列中找出一子序列的最后一次出现的位置 |
||
search |
在序列中找出一子序列的第一次出现的位置 |
||
search_n |
在序列中找出一值连续n次出现的位置 |
||
3 |
计数 |
count |
在序列中统计某个值出现的次数 |
count_if |
在序列中统计与某谓词(表达式)匹配的次数 |
||
4 |
比较 |
equal |
两个序列中的对应元素都相同时为真 |
mismatch |
找出两个序列相异的第一个元素 |
循环
for_each
//原形:
template<class InIt, class Fun>
Fun for_each(InIt first, InIt last, Fun f);
打印向量中每个整形元素的立方
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void PrintCube(int n) //打印n的立方
{
cout << n * n * n << " " ;
}
void main()
{
const int VECTOR_SIZE = 8 ;
typedef vector<int > IntVector ; //为向量类起一个别名
typedef IntVector::iterator IntVectorIt ;//为向量类迭代器起一个别名
IntVector Numbers(VECTOR_SIZE) ; //初始化向量类,大小为VECTOR_SIZE(8)
IntVectorIt start, end, it ; //定义向量类迭代指针
for (int i = 0; i < VECTOR_SIZE; i++) //通过数组方式给向量类赋值
Numbers[i] = i + 1 ;
start = Numbers.begin() ; // start 表示迭代器起始指针
end = Numbers.end() ; // end 表示迭代器结束指针
cout << "Numbers { " ; //打印向量中的各个元素
for(it = start; it != end; it++)
cout << *it << " " ;
cout << " }\n" << endl ;
for_each(start, end, PrintCube) ;//[start,end)间每个元素作为PrintCube的参数传入并执行
cout << "\n" ;
}
(1)for_each函数各参数的含义。start,end表示向量的起始迭代指针、结束迭代指针,不是具体的值,比如for_each(start[0], end, PrintCube)是错误的,因为start[0]表示的是向量中第一个元素的值1。但for_each(&start[0], end, PrintCube)是正确的, 因为&start[0]表示的是第一个元素的地址。
(2)PrintCube函数有且必须只有一个参数,且参数类型与向量的模板类型必须一致。
求整数向量的和、最大值、最小值 分析:由于必须遍历整形向量的每个元素,因此可以应用for_each函数。当然可以应用全局函数的方法完成所需功能,但更好的方法是定义一个类,如下所示。
#include <iostream>
#include <algorithm>
using namespace std;
class PrintInfo
{
private:
int nSum;
int nMax;
int nMin;
int count;
public:
PrintInfo():count(0),nSum(0) {}
int GetSum() {return nSum;}
int GetMax() {return nMax;}
int GetMin() {return nMin;}
void operator() (int x)
{
if(count == 0)
{
nMax = x;
nMin = x;
}
else
{
if(nMax < x)
{
nMax = x;
}
if(nMin > x)
{
nMin = x;
}
}
nSum += x;
count++ ;
}
};
int main()
{
int A[] = {1, 4, 2, 8, 5, 7};
const int N = sizeof(A) / sizeof(int);
PrintInfo P = for_each(A, A + N, PrintInfo());
cout << "总和是:" << P.GetSum() << endl;
cout << "最大值:" << P.GetMax() << endl;
cout << "最小值:" << P.GetMin() << endl;
return 0;
}
查询
①find 原形:
template<class InIt, class T>
InIt find(InIt first, InIt last, const T& val);
该函数是查询[first, last)间迭代器对应的元素值是否有等于val的,若有则返回其迭代器指针,若无则返回last。可知查询元素的个数范围是N:[0, last-first), 由于要判定*(first+N)==val, 因此模板T对应的类必须重载运算符“operator==”。
②find_if 原型:
template<class InIt, class Pred>
InIt find_if(InIt first, InIt last, Pred pr);
参数说明 该函数是查询[first, last)间迭代器对应的元素*(first+i),若pr(*(first+i))返回true,则返回此时的迭代器指针,表明满足条件的元素已找到;若没有找到则返回last。
③find_first_of 原型:
template<class FwdIt1, class FwdIt2>
FwdIt1 find_first_of(FwdIt1 first1, FwdIt1 last1,FwdIt2 first2, FwdIt2 last2);
template<class FwdIt1, class FwdIt2, class Pred>
FwdIt1 find_first_of(FwdIt1 first1, 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<class FwdIt>
FwdIt adjacent_find(FwdIt first, FwdIt last);
template<class FwdIt, class Pred>
FwdIt adjacent_find(FwdIt first, FwdIt last, Pred pr);
第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>
FwdIt1 find_end(FwdIt1 first1, FwdIt1 last1,FwdIt2 first2, FwdIt2 last2);
template<class FwdIt1, class FwdIt2, class Pred >
FwdIt1 find_end(FwdIt1 first1, FwdIt1 last1,FwdIt2 first2, FwdIt2 last2, Pred pr);
第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, class FwdIt2>
FwdIt1 search(FwdIt1 first1, FwdIt1 last1,FwdIt2 first2, FwdIt2 last2);
template<class FwdIt1, class FwdIt2, class Pred >
FwdIt1 search(FwdIt1 first1, FwdIt1 last1,FwdIt2 first2, FwdIt2 last2,Pred pr);
第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>
FwdIt search_n(FwdIt first, FwdIt last,Dist n, const T& val);
template<class FwdIt, class Dist, class T, class Pred >
FwdIt search_n(FwdIt first, FwdIt last,Dist n, const T& val, Pred pr);
第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;
}
void main()
{
int a[] = {1,2,2,2,3,4,4,5,6,7,1,2,2,3} ;
int nSize = sizeof(a)/sizeof(int);
cout << "原始数组:" << endl;
for(int i=0; i<nSize; i++)
{
cout << a[i] << "\t";
}
cout << endl << endl;
int *p1 = find(a, a+nSize, 3);
if(p1!=a+nSize)
cout << "(find)首次等于3的位置:" << p1-a << "\t值:" <<*p1 << endl;
int *p2 = find_if(a, a+nSize, greater);
if(p2!=a+nSize)
cout << "(find_if)首次大于4的位置:" << p2-a << "\t值:" <<*p2 << endl;
int b[] = {10,12,6};
int nSize2 = sizeof(b)/sizeof(int);
int *p3 = find_first_of(a, a+nSize, b, b+nSize2);
if(p3!=a+nSize)
cout << "(find_first_of)首次在a数组中发现b数组[10,12,6]中元素位置:" << p3-a << "\t值:" <<*p3<< endl;
int *p4 = adjacent_find(a, a+nSize);
if(p4!=a+nSize)
cout << "(adjacent_find)首次相邻元素相同位置:" << p4-a << "\t值:" <<*p4 << endl;
int c[] = {2,3};
int nSize3 = sizeof(c)/sizeof(int);
int *p5 = find_end(a, a+nSize, c, c+nSize3);
if(p5!=a+nSize)
cout <<"最后一次匹配c数组[2,3]位置:"<<p5-a << endl;
int *p6 = search(a, a+nSize, c, c+nSize3);
if(p6!=a+nSize)
cout <<"首次匹配c数组[2,3]位置:"<<p6-a << endl;
int *p7 = search_n(a, a+nSize, 3, 2);
if(p7!=a+nSize)
cout <<"首次出现3个2的位置:" << p7 - a << endl;
}
【例8.5】已知学生基本属性:学号(整形,关键字),姓名,成绩。现在要求编相关的功能类,能添加学生对象,并具有下列查询功能:(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 strName; //姓名
int grade; //成绩
static int mark; //查询标识
Student(int NO, string strName,int grade)
{
this->NO = NO;
this->strName = strName;
this->grade = grade;
}
bool operator==(int n) //用于学号或成绩查询
{
if(mark == NO_FIND) //按学号查询
return NO==n;
else //按成绩查询
return grade==n;
}
bool operator==(string name)//用于按姓名查询
{
return strName.compare(name) == 0;
}
};
int Student::mark = -1;
ostream& operator << (ostream& os, Student& s)
{
os << s.NO << "\t" << s.strName << "\t" << s.grade ;
return os;
}
class StudFindIf //用于find_if函数的类
{
private:
int low;
int high;
public:
StudFindIf(int low, int high)
{
this->low = low;
this->high= high;
}
bool operator()(Student & s)
{
return s.grade>=low && s.grade <=high;
}
};
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 << "学号: " << no << "没有查询记录" << endl;
}
return true;
}
bool FindByNO(int no[], int nSize)//按学号数组查询
{
bool bFind = false;
Student::mark = NO_FIND;
vector<Student>::iterator te = find_first_of(vecStud.begin(), vecStud.end(),no, no+nSize);
while(te != vecStud.end())
{
bFind = true;
cout << *te << endl;
te ++;
te = find_first_of(te, vecStud.end(), no, no+nSize);
}
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 << "姓名:" << name << "没有查询记录" << 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 << "成绩:" << grade << "没有查询记录" << endl;
}
return true;
}
bool FindByRange(int low, int high)//按成绩范围查询
{
bool bFind = false;
StudFindIf sf(low, high);
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;
}
};
void 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) ;//返回学号等于102的迭代器指针
cout << "按姓名查询(张三):" << endl;
manage.FindByName("张三");
cout << "按成绩查询(50):" << endl;
manage.FindByGrade(50);
int a[] = {101,105,103,107};
cout << "按学号组{101,105,103,107}查询:" << endl;
manage.FindByNO(a, sizeof(a)/sizeof(int));
cout << "按成绩范围[55,70]查询" << endl;
manage.FindByRange(55, 70);
}
计数
①count原型:
template<class InIt, class T>
size_t count(InIt first, InIt last,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。
查询有多少学生成绩为80分。
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
class Student
{
public:
int NO; //学号
string strName; //姓名
int grade; //成绩
Student(int NO, string strName, int grade)
{
this->NO = NO;
this->strName = strName;
this->grade = grade;
}
bool operator==(int grade)
{
return this->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);
int nCount = count(v.begin(), v.end(), 80);
cout << "成绩为80分的人数为:" << nCount << endl;
}
比较
①equal原型:
template<class InIt1, class InIt2>
bool equal(InIt1 first, InIt1 last, InIt2 x);
template<class InIt1, class InIt2, class Pred >
bool equal(InIt1 first, InIt1 last, InIt2 x, Pred pr);
第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, class InIt2> 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, Pred pr);
第1个原型含义是:对两个迭代器而言,返回第1对元素不相等时的迭代器指针,保存在pair对象中。pair有两个成员变量:first,second,分别表示Init1及Init2不相等时的迭代指针。 第2个原型与第1个类似, 只不过要定义预判定函数pr(*(first1+N), *(first2+M))。
比较两个整形数组是否相等
#include <algorithm>
#include <iostream>
using namespace std;
int main() {
int A1[] = { 3, 1, 4, 1, 5, 9, 3 };
int A2[] = { 3, 1, 4, 2, 8, 5, 7 };
const int N = sizeof(A1) / sizeof(int);
cout << "Result of comparison: " << equal(A1, A1 + N, A2) << endl;
return 0;
}
寻找两个整形数组元素不相等时的元素值
#include <algorithm>
#include <iostream>
using namespace std;
int main() {
int A1[] = { 3, 1, 4, 1, 5, 9, 3 };
int A2[] = { 3, 1, 4, 2, 8, 5, 7 };
const int N = sizeof(A1) / sizeof(int);
pair<int*, int*> result = mismatch(A1, A1 + N, A2);
cout << "The first mismatch is in position " << result.first - A1 << endl;
cout << "Values are: " << *(result.first) << ", " << *(result.second) << endl;
return 0;
}
查询第一对成绩不相等学生的信息
#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Student
{
public:
int NO; //学号
string strName; //姓名
int grade; //成绩
Student(int NO, string strName, int grade)
{
this->NO = NO;
this->strName = strName;
this->grade = grade;
}
bool operator==(Student& s)
{
return this->grade == s.grade;
}
};
int main() {
vector<Student> v1;
Student s1(1001, "aaa", 90);
Student s2(1002, "bbb", 80);
Student s3(1003, "ccc", 70);
v1.push_back(s1),v1.push_back(s2),v1.push_back(s3);
vector<Student> v2;
Student s4(1004, "ddd", 90);
Student s5(1005, "eee", 80);
Student s6(1006, "fff", 75);
v2.push_back(s4),v2.push_back(s5),v2.push_back(s6);
cout << "查询第一对成绩不相等学生的信息:" << endl;
pair<Student*, Student*> result = mismatch(v1.begin(), v1.end(), v2.begin());
Student& stu1 = *result.first;
Student& stu2 = *result.second;
cout <<"学号:"<<stu1.NO<<"\t姓名:"<<stu1.strName<<"\t成绩:"<<stu1.grade<<endl;
cout <<"学号:"<<stu2.NO<<"\t姓名:"<<stu2.strName<<"\t成绩:"<<stu2.grade<<endl;
return 0;
}