STL学习(17):非变异算法

  • 循环
  • 查询
  • 计数
  • 比较

非变异算法主要包含以下函数

序号

功能

函数名称

说明

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;
}

猜你喜欢

转载自blog.csdn.net/QQ2558030393/article/details/93469955