当前位置:   article > 正文

从0到1入门C++编程——11 函数对象及算法介绍

从0到1入门C++编程——11 函数对象及算法介绍

函数对象

重载函数调用操作符的类,其对象常称为函数对象。函数对象使用重载的()时,行为类似函数调用,也称仿函数。函数对象的本质是一个类,而不是一个函数。
函数对象的特点:函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值;函数对象超出普通函数的概念,可以有自己的状态;函数对象可以作为参数传递。
函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值,举例如下。

class myAdd
{
public:
	int operator()(int a,int b)  //有参数,有返回值
	{
		return a + b;
	}
};

myAdd m;
cout<<"result = "<<m(10,20)<<endl;   //仿函数的调用
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

函数对象超出普通函数的概念,可以有自己的属性状态,例子如下。

class myPrint
{
public:
	myPrint()
	{
		this->count = 0;
	}
	void operator()(string s)
	{
		cout<<s<<endl;
		count++;
	}
	int count;   //函数对象可以定义自己的属性
};

int main()
{
	myPrint m;
	m("Hello");
	m("Hello");
	m("Hello");
	cout<<"仿函数调用次数:"<<m.count<<endl;
	system("pause");
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

函数对象可以作为参数传递,例子如下。

class myPrint
{
public:
	void operator()(string s)
	{
		cout<<s<<endl;
	}
};

void fun(myPrint &m,string s)  //函数对象作为函数参数传递
{
	m(s);
}

int main()
{
	myPrint m;
	fun(m,"Hello");
	system("pause");
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

1、谓词

返回bool类型的仿函数称为谓词。如果operator()接受一个参数,就叫做一元谓词,接受两个参数就叫做二元谓词。
一元谓词的简单代码示例如下,注意使用find_if()返回的是一个迭代器,第三个参数既可以传入匿名对象,也可以传入实例化对象进行调用。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

class Judge
{
public:
	bool operator()(int a)   //一元谓词
	{
		return a > 3;
	}
};

void fun()
{
	vector<int> v;
	for(int i=0;i<5;i++)
	{
		v.push_back(i+1);
	}
	Judge j;
	vector<int>::iterator i = find_if(v.begin(),v.end(),Judge());  //传入匿名对象
	//vector<int>::iterator i = find_if(v.begin(),v.end(),j);  //传入实例化对象
	if(i == v.end())
	{
		cout<<"在容器中未找到大于3的值"<<endl;
	}
	cout<<"容器中第一个大于3的值是: "<<*i<<endl;
}

int main()
{
	fun();
	system("pause");
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

二元谓词的简单代码示例如下。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

class mySort
{
public:
	bool operator()(int a,int b)  //二元谓词
	{
		return a > b;
	}
};

void printVector(vector<int> &v)
{
	for(vector<int>::iterator i = v.begin();i!=v.end();i++)
	{
		cout<<*i<<" ";
	}
	cout<<endl;
}

void fun()
{
	vector<int> v;
	v.push_back(2);
	v.push_back(1);
	v.push_back(5);
	v.push_back(4);
	v.push_back(3);
	cout<<"原序列: ";
	printVector(v);
	sort(v.begin(),v.end());
	cout<<"升序排列: ";
	printVector(v);
	mySort ms;
	sort(v.begin(),v.end(),ms); 
	//sort(v.begin(),v.end(),mySort());  //与上面的两行效果相同
	cout<<"降序排列: ";
	printVector(v);
}

int main()
{
	fun();
	system("pause");
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

上面程序的运行结果如下图所示。
在这里插入图片描述

2、内建函数对象

内建函数对象分为算术仿函数、关系仿函数、逻辑仿函数。仿函数产生的对象,其用法和一般函数相同,使用内建函数对象需要引入以下头文件。

#include <functional>
  • 1

(1) 算术仿函数

算术仿函数就是实现四则运算、取模取反操作的,主要的关系仿函数有:

template<class T> T plus<T>;
template<class T> T minus<T>;
template<class T> T multiplies<T>;
template<class T> T divides<T>;
template<class T> T modulus<T>;
template<class T> T negate<T>;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

算术仿函数的简单使用例子如下。

#include <iostream>
#include <functional>
using namespace std;

void fun()
{
	plus<int> p;
	cout<<"20+10="<<p(20,10)<<endl;
	minus<int> m;
	cout<<"20-10="<<m(20,10)<<endl;
	multiplies<int> mp;
	cout<<"20*10="<<mp(20,10)<<endl;
	divides<int> d;
	cout<<"20/10="<<d(20,10)<<endl;
	modulus<int> mod;  //取模
	cout<<"20%10="<<mod(20,10)<<endl;
	negate<int> n;  //取反——单目运算
	cout<<"10取反后是: "<<n(10)<<endl;
}

int main()
{
	fun();
	system("pause");
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

上面程序的运行结果如下图所示。
在这里插入图片描述

(2) 关系仿函数

关系仿函数是实现关系对比的,主要的关系仿函数有:

template<class T> bool equal_to<T>;   // =
template<class T> bool not_equal_to<T>;  // !=
template<class T> bool greater<T>;  // >
template<class T> bool greater_equal<T>;  // >=
template<class T> bool less<T>;   // <
template<class T> bool less_equal<T>;  // <=
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

转到使用两个参数的sort()函数定义,如下,默认使用的是<,也就是升序排列。

template<class _RanIt> inline
	void sort(_RanIt _First, _RanIt _Last)
	{	// order [_First, _Last), using operator<
	_DEBUG_RANGE(_First, _Last);
	_Sort(_Unchecked(_First), _Unchecked(_Last), _Last - _First);
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

前面也提到过,可以通过自己写仿函数定义排序的规则。

class Compare
{
public:
	bool operator()(int a,int b)
	{
		return a > b;
	}
};

sort(v.begin(),v.end(),Compare());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

而内建函数中就有这样的关系仿函数,同样按照降序排列,就不用自己再写仿函数了,在谓词位置直接将内建函数写上就能实现相同的功能。

sort(v.begin(),v.end(),greater<int>()); 
  • 1

完整的示例代码如下。

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;

void printVector(vector<int> &v)
{
	for(vector<int>::iterator i=v.begin();i!=v.end();i++)
	{
		cout<<*i<<" ";
	}
	cout<<endl;
}

class Compare
{
public:
	bool operator()(int a,int b)
	{
		return a > b;
	}
};

void fun()
{
	vector<int> v;
	v.push_back(2);
	v.push_back(1);
	v.push_back(4);
	v.push_back(3);
	cout<<"原序列: ";
	printVector(v);
	sort(v.begin(),v.end());
	cout<<"升序序列: ";
	printVector(v);
	sort(v.begin(),v.end(),Compare());
	cout<<"降序序列: ";
	printVector(v);
	sort(v.begin(),v.end(),less<int>());  //内建函数对象
	cout<<"升序序列: ";
	printVector(v);
}

int main()
{
	fun();
	system("pause");
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

上面程序的运行结果如下图所示。
在这里插入图片描述

(3) 逻辑仿函数

逻辑仿函数是实现逻辑运算的,主要的逻辑仿函数有:

template<class T> bool logical_and<T>;  //与
template<class T> bool logical_or<T>;   //或
template<class T> bool logical_not<T>;  //非
  • 1
  • 2
  • 3

关于逻辑仿函数的应用示例代码如下。

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;

void printVector(vector<int> &v)
{
	for(vector<int>::iterator i=v.begin();i!=v.end();i++)
	{
		cout<<*i<<" ";
	}
	cout<<endl;
}

void fun()
{
	vector<int> v1;
	v1.push_back(0);
	v1.push_back(1);
	v1.push_back(0);
	v1.push_back(1);
	cout<<"v1序列: ";
	printVector(v1);
	vector<int> v2;
	v2.resize(v1.size());   //给v2指定与v1相同的空间大小
	transform(v1.begin(),v1.end(),v2.begin(),logical_not<int>());  //将v1搬运到v2并做取反操作
	cout<<"v2序列: ";
	printVector(v2);
}

int main()
{
	fun();
	system("pause");
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

上面程序的运行结果如下图所示。
在这里插入图片描述


常用算法

算法的主要头文件有以下几个:

#include <algorithm>   //比较大,包括比较、交换、查找、遍历、复制、修改等操作
#include <functional>  //定义了一些模板类,用以声明函数对象
#include <numeric>   //体积较小,只包括几个在序列上面进行简单数学运算的模板函数
  • 1
  • 2
  • 3

1、常用遍历算法

(1) for_each

for_each用于遍历一个容器,其函数原型如下。

for_each(iterator begin,iterator end,_func);  //三个参数依次是:迭代器起始位置,结束位置,函数或者函数对象
  • 1

需要注意的是,目标容器在搬运之前一定要开辟好空间。
for_each的简单使用示例如下。

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;

void print_1(int a)
{
	cout<<a<<" ";
}

class print_2
{
public:
	void operator()(int a)  //无返回值
	{
		cout<<a<<" ";
	}
};

void fun()
{
	vector<int> v;
	v.push_back(2);
	v.push_back(1);
	v.push_back(3);
	v.push_back(4);
	cout<<"普通函数遍历v序列: ";
	for_each(v.begin(),v.end(),print_1);  //普通函数
	cout<<endl;
	cout<<"仿函数遍历v序列: ";
	for_each(v.begin(),v.end(),print_2());  //仿函数
	cout<<endl;
}

int main()
{
	fun();
	system("pause");
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

(2) transform

transform用于搬运一个容器到另一个容器中,其函数原型如下。

transform(iterator begin1,iterator end1,iterator begin2,_func);  //四个参数依次是:源容器的起止迭代器,目标容器的起始迭代器,函数或者函数对象
  • 1

transform的简单使用示例如下。

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;

void print(int a)
{
	cout<<a<<" ";
}

class Transform
{
public:
	int operator()(int a)
	{
		return a*2;  //搬运后每个数乘2
	}
};

void fun()
{
	vector<int> v;
	v.push_back(2);
	v.push_back(1);
	v.push_back(3);
	v.push_back(4);
	cout<<"原序列: ";
	for_each(v.begin(),v.end(),print);
	cout<<endl;
	vector<int> v1;
	v1.resize(v.size());  //指定目标容器的大小
	transform(v.begin(),v.end(),v1.begin(),Transform());
	cout<<"搬运操作后的序列: ";
	for_each(v1.begin(),v1.end(),print);
	cout<<endl;
}

int main()
{
	fun();
	system("pause");
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

上面程序的运行结果如下图所示。
在这里插入图片描述

2、常用查找算法

常用的查找算法有以下几个。

find();   //查找元素
find_if();  //按条件查找
adjacent_find();  //查找相邻重复元素
binary_search();  //二分查找法
count();  //统计元素个数
count_if();  //按条件统计元素个数
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

(1) find和find_if

find用来查找指定元素,找到就返回指定元素的迭代器,找不到就返回结束为止的迭代器end(),其函数原型如下。

find(iterator begin,iterator end,value);    //参数分别是:开始迭代器、结束迭代器、要查找的元素
  • 1

下面的代码示例提供了find查找内置数据类型和自定义数据类型。

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;

class Person
{
public:
	Person(string name,int age)
	{
		this->name = name;
		this->age =age;
	}
	bool operator==(const Person &p)   //重载 ==
	{
		if(this->age == p.age && this->name == p.name)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	string name;
	int age;
};

void fun1()  //内置数据类型的查找
{
	vector<int> v;
	for(int i=0;i<5;i++)
	{
		v.push_back(i+1);
	}
	vector<int>::iterator i=find(v.begin(),v.end(),3);
	if(i != v.end())
	{
		cout<<"元素"<<*i<<"在容器中!"<<endl;
	}
	else
	{
		cout<<"元素不在容器中!"<<endl;
	}
}

void fun2()  //自定义数据类型的查找
{
	vector<Person> v;
	Person p1("A",10);
	Person p2("B",20);
	Person p3("C",30);
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	Person p4("A",10);
	vector<Person>::iterator i=find(v.begin(),v.end(),p4);
	if(i != v.end())
	{
		cout<<"元素在容器中! name = "<<i->name<<"  age = "<<i->age<<endl;
	}
	else
	{
		cout<<"元素不在容器中!"<<endl;
	}
}

int main()
{
	fun1();
	fun2();
	system("pause");
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75

上面程序的运行结果如下图所示。
在这里插入图片描述

(2) find_if

find根据给定的条件来查找元素,找到就返回指定元素的迭代器,找不到就返回结束为止的迭代器end(),其函数原型如下。

find_if(iterator begin,iterator end,_Pred);  //参数分别是:开始迭代器、结束迭代器、函数或者谓词
  • 1

find_if()应用示例的代码如下。

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;

class Person
{
public:
	Person(string name,int age)
	{
		this->name = name;
		this->age =age;
	}
	string name;
	int age;
};

class Compare1
{
public:
	bool operator()(int value)
	{
		return value > 3;
	}
};

class Compare2
{
public:
	bool operator()(Person &p)
	{
		return p.age > 20;
	}
};

void fun1()  //内置数据类型的查找
{
	vector<int> v;
	for(int i=0;i<5;i++)
	{
		v.push_back(i+1);
	}
	vector<int>::iterator i=find_if(v.begin(),v.end(),Compare1());
	if(i != v.end())
	{
		cout<<"元素在容器中! 找到第一个满足条件的值是: "<<*i<<endl;
	}
	else
	{
		cout<<"元素不在容器中!"<<endl;
	}
}

void fun2()  //自定义数据类型的查找
{
	vector<Person> v;
	Person p1("A",10);
	Person p2("B",20);
	Person p3("C",30);
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	vector<Person>::iterator i=find_if(v.begin(),v.end(),Compare2());
	if(i != v.end())
	{
		cout<<"元素在容器中! name = "<<i->name<<"  age = "<<i->age<<endl;
	}
	else
	{
		cout<<"元素不在容器中!"<<endl;
	}
}

int main()
{
	fun1();
	fun2();
	system("pause");
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81

上面程序的运行结果如下图所示。
在这里插入图片描述

(3) adjacent_find

adjacent_find用来查找相邻重复元素,其返回值是相邻元素的第一个位置的迭代器,函数原型如下。

adjacent_find(iterator begin,iterator end);  //参数分别是:开始迭代器、结束迭代器
  • 1

adjacent_find的简单应用示例代码如下。

void fun()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(3);
	v.push_back(3);
	v.push_back(2);
	v.push_back(4);
	vector<int>::iterator i=adjacent_find(v.begin(),v.end());
	if(i != v.end())
	{
		cout<<"容器中有相邻重复元素,其值为: "<<*i<<endl;
	}
	else
	{
		cout<<"容器中没有相邻重复元素!"<<endl;
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

(4) binary_search

binary_search用来查找指定元素是否存在,其函数原型如下。

bool binary_search(iterator begin,iterator end,value);  //三个参数分别是迭代器起始位置,要查找的值
  • 1

查找到了就返回true,否则返回false,因为其返回的不是迭代器位置,因此无法输出打印。
需要注意的是,binary_search在无序序列中不可用。
binary_search的简单应用示例代码如下。

void fun()
{
	vector<int> v;
	for(int i=1;i<6;i++)
	{
		v.push_back(i);
	}
	bool ret = binary_search(v.begin(),v.end(),4);
	if(ret)
	{
		cout<<"该元素存在!"<<endl;
	}
	else
	{
		cout<<"该元素不存在!"<<endl;
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

(5) count

count用来统计元素个数,其函数原型如下。

count(iterator begin,iterator end,value);  //三个参数分别是迭代器起始位置,要统计的值
  • 1

关于count函数的应用示例代码如下。

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;

class Person
{
public:
	Person(string name,int age)
	{
		this->name = name;
		this->age = age;
	}
	bool operator==(const Person &p)
	{
		if(this->age == p.age)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	string name;
	int age;
};

void fun1()   //统计内置数据类型
{
	vector<int> v;
	v.push_back(2);
	v.push_back(2);
	v.push_back(3);
	v.push_back(1);
	v.push_back(2);
	int ret = count(v.begin(),v.end(),2);
	cout<<"容器中2的个数为: "<<ret<<endl;
}

void fun2()   //统计自定义数据类型
{
	Person p1("A",10);
	Person p2("B",15);
	Person p3("C",20);
	Person p4("D",10);
	vector<Person> v;
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);
	int ret = count(v.begin(),v.end(),p1);
	cout<<"容器中年龄为10的人数为: "<<ret<<endl;
}

int main()
{
	fun1();
	fun2();
	system("pause");
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63

上面程序的运行结果如下图所示。
在这里插入图片描述

(6) count_if

count_if用来按条件统计元素个数,其函数原型如下。

count_if(iterator begin,iterator end,_Pred);  //三个参数分别是迭代器起始位置,谓词
  • 1

关于count_if函数的应用示例代码如下。

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;

class Person
{
public:
	Person(string name,int age)
	{
		this->name = name;
		this->age = age;
	}
	string name;
	int age;
};

class Compare1
{
public:
	bool operator()(int value)
	{
		return value > 2;
	}
};

void fun1()   //统计内置数据类型
{
	vector<int> v;
	v.push_back(2);
	v.push_back(4);
	v.push_back(3);
	v.push_back(1);
	v.push_back(5);
	int ret = count_if(v.begin(),v.end(),Compare1());
	cout<<"容器中大于2的元素个数为: "<<ret<<endl;
}

class Compare2
{
public:
	bool operator()(const Person &p)
	{
		return p.age > 20;
	}
};

void fun2()   //统计自定义数据类型
{
	Person p1("A",10);
	Person p2("B",40);
	Person p3("C",20);
	Person p4("D",30);
	vector<Person> v;
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);
	int ret = count_if(v.begin(),v.end(),Compare2());
	cout<<"容器中年龄大于20的人数为: "<<ret<<endl;
}

int main()
{
	fun1();
	fun2();
	system("pause");
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70

上面程序的运行结果如下图所示。
在这里插入图片描述

3、常用排序算法

常用的排序算法有以下几个。

sort();   //对容器内元素进行排序
random_shuffle();  //洗牌,对指定范围内的元素随机调整次序
merge();  //容器元素合并,并存储到另一容器中,两个容器需是有序序列
reverse();  //反转指定范围的元素
  • 1
  • 2
  • 3
  • 4

(1) sort

sort用来对容器的元素进行排序,其函数原型如下。

sort(iterator begin,iterator end,_Pred);   //三个参数分别是迭代器起始位置,谓词位置可以选填,不填代表从小到大排列
  • 1

关于sort的应用示例代码如下。

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;

void printVector(int value)
{
	cout<<value<<" ";
}

void fun()
{
	vector<int> v;
	v.push_back(2);
	v.push_back(4);
	v.push_back(3);
	v.push_back(1);
	v.push_back(5);
	cout<<"源序: ";
	for_each(v.begin(),v.end(),printVector);
	cout<<endl;
	sort(v.begin(),v.end());
	cout<<"升序: ";
	for_each(v.begin(),v.end(),printVector);
	cout<<endl;
	cout<<"降序: ";
	sort(v.begin(),v.end(),greater<int>());
	for_each(v.begin(),v.end(),printVector);
	cout<<endl;
}

int main()
{
	fun();
	system("pause");
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

上面程序的运行结果如下图所示。
在这里插入图片描述

(2) random_shuffle

random_shuffle对指定范围内的元素随机调整次序,函数原型如下。

random_shuffl(iterator begin,iterator end);
  • 1

关于random_shuffle的应用示例代码如下。

#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>
using namespace std;

void printVector(int value)
{
	cout<<value<<" ";
}

void fun()
{
	vector<int> v;
	for(int i=1;i<=10;i++)
	{
		v.push_back(i);
	}
	cout<<"源序: ";
	for_each(v.begin(),v.end(),printVector);
	cout<<endl;
	random_shuffle(v.begin(),v.end());
	cout<<"洗牌后: ";
	for_each(v.begin(),v.end(),printVector);
	cout<<endl;
}

int main()
{
	srand((unsigned int)time(NULL));  //随机数种子
	fun();
	system("pause");
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

上面程序的运行结果如下图所示。
在这里插入图片描述

(3) merge

merge用来将两个容器的元素合并,并存储到一个容器中,需要注意的是,两个容器需是有序序列,合并后得到的序列依然是个有序序列,merge函数原型如下。

merge(iterator begin1,iterator end1,iterator begin2,iterator end2,iterator dest);  //参数分别是容器1和容器2开始结束的迭代器,以及目标容器的开始迭代器
  • 1

关于merge的应用示例代码如下。

void fun()
{
	vector<int> v1;
	for(int i=1;i<=3;i++)
	{
		v1.push_back(i);
	}
	vector<int> v2;
	for(int i=4;i<=6;i++)
	{
		v2.push_back(i);
	}
	vector<int> v;
	v.resize(v1.size()+v2.size());  //给目标容器指定大小
	merge(v1.begin(),v1.end(),v2.begin(),v2.end(),v.begin());  //合并两个容器
	for_each(v.begin(),v.end(),printVector);
	cout<<endl;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

(4) reverse

reverse用来将容器内的元素进行反转,其函数原型如下。

reverse(iterator begin,iterator end);
  • 1

关于reverse的应用示例代码如下。

void fun()
{
	vector<int> v;
	v.push_back(3);
	v.push_back(1);
	v.push_back(4);
	v.push_back(2);
	cout<<"反转前: ";
	for_each(v.begin(),v.end(),printVector);
	cout<<endl;
	reverse(v.begin(),v.end());   //反转序列
	cout<<"反转后: ";
	for_each(v.begin(),v.end(),printVector);
	cout<<endl;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

4、常用拷贝和替换算法

常用拷贝和替换算法主要有以下几个。

copy();   //将容器内指定范围的元素拷贝到另一个容器中
replace();   //将容器内指定范围的旧元素替换为新元素
replace_if();  //将容器内指定范围内满足条件的元素进行替换
swap();  //互换两个容器的元素
  • 1
  • 2
  • 3
  • 4

(1) copy

copy用来将容器内指定范围的元素拷贝到另一个容器中,其函数原型如下。

copy(iterator begin,iterator end,iterator dest);
  • 1

关于copy的应用示例代码如下。

void fun()
{
	vector<int> v1;
	v1.push_back(3);
	v1.push_back(1);
	v1.push_back(4);
	v1.push_back(2);
	vector<int> v2;
	v2.resize(v1.size());  //拷贝前先分配空间
	copy(v1.begin(),v1.end(),v2.begin());
	for_each(v2.begin(),v2.end(),printVector);
	cout<<endl;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

(2) replace

replace用来将容器内指定范围的旧元素替换为新元素,其函数原型如下。

replace(iterator begin,iterator end,T oldvalue,T newvalue);
  • 1

关于replace的应用示例代码如下。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

class printVector
{
public:
	void operator()(int value)
	{
		cout<<value<<" ";
	}
};

void fun()
{
	vector<int> v;
	v.push_back(3);
	v.push_back(2);
	v.push_back(1);
	v.push_back(2);
	cout<<"替换前: ";
	for_each(v.begin(),v.end(),printVector());
	cout<<endl;
	cout<<"替换后: ";
	replace(v.begin(),v.end(),2,4);
	for_each(v.begin(),v.end(),printVector());
	cout<<endl;
}

int main()
{
	fun();
	system("pause");
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

上面程序的运行结果如下图所示。
在这里插入图片描述

(3) replace_if

replace_if用来将容器内指定范围内满足条件的元素进行替换,其函数原型如下。

replace_if(iterator begin,iterator end,_Pred,T newvalue);
  • 1

关于replace_if的应用示例代码如下。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

class printVector
{
public:
	void operator()(int value)
	{
		cout<<value<<" ";
	}
};

class myReplace
{
public:
	bool operator()(int value)
	{
		return value >= 2;  //选出容器中大于等于2的数
	}
};

void fun()
{
	vector<int> v;
	v.push_back(3);
	v.push_back(2);
	v.push_back(4);
	v.push_back(1);
	v.push_back(2);
	cout<<"替换前: ";
	for_each(v.begin(),v.end(),printVector());
	cout<<endl;
	cout<<"替换后: ";
	replace_if(v.begin(),v.end(),myReplace(),0);  //将容器中大于等于2的数替换为0
	for_each(v.begin(),v.end(),printVector());
	cout<<endl;
}

int main()
{
	fun();
	system("pause");
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

上面程序的运行结果如下图所示。
在这里插入图片描述

(4) swap

swap用来互换两个容器的元素,其函数原型如下。

swap(container c1,container c2);
  • 1

关于swap的应用示例代码如下。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

void printVector(vector<int> &v)
{
	for(vector<int>::iterator i=v.begin();i!=v.end();i++)
	{
		cout<<*i<<" ";
	}
	cout<<endl;
};

void fun()
{
	vector<int> v1,v2;
	for(int i=0;i<5;i++)
	{
		v1.push_back(i+1);
		v2.push_back(i+6);
	}
	cout<<"--------交换前--------"<<endl;
	cout<<"v1: ";
	printVector(v1);
	cout<<"v2: ";
	printVector(v2);
	cout<<"--------交换后--------"<<endl;
	swap(v1,v2);   //交换两个容器
	cout<<"v1: ";
	printVector(v1);
	cout<<"v2: ";
	printVector(v2);
}

int main()
{
	fun();
	system("pause");
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

上面程序的运行结果如下图所示。
在这里插入图片描述

5、常用算术生成算法

算术生成算法在使用的时候需要包含下面的头文件。

#include <numeric>
  • 1

常用算术生成算法有以下几个。

accumulate();  //计算容器指定区间内元素累计总和
fill();  //给容器中指定区间填充指定的元素
  • 1
  • 2

(1) accumulate

accumulate用来计算容器指定区间内元素累计总和,其函数原型如下。

accumulate(iterator begin,iterator end,T value);  //value指的是起始的累加值
  • 1

关于accumulate的应用示例代码如下。

void fun()
{
	vector<int> v;
	for(int i=0;i<=100;i++)
	{
		v.push_back(i);
	}
	int sum = accumulate(v.begin(),v.end(),0);  //累加容器中指定区间内的元素,即计算0-100之和
	cout<<"sum = "<<sum<<endl;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

(2) fill

fill用来给容器中指定区间填充指定的元素,其函数原型如下。

fill(iterator begin,iterator end,T value);   //value指的是要填充的值
  • 1

关于fill的应用示例代码如下。

#include <iostream>
#include <vector>
#include <numeric>
using namespace std;

void printVector(vector<int> &v)
{
	for(vector<int>::iterator i=v.begin();i!=v.end();i++)
	{
		cout<<*i<<" ";
	}
	cout<<endl;
};

void fun()
{
	vector<int> v;
	v.resize(10);  //指定大小
	fill(v.begin(),v.begin()+3,1);  //填充
	fill(v.begin()+3,v.begin()+6,2);
	fill(v.begin()+6,v.end(),3);
	printVector(v);
}

int main()
{
	fun();
	system("pause");
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

6、常用集合算法

常用集合算法主要用来计算两个容器之间的交集、并集和差集。
主要的集和算法有以下几个,在求两个容器的交集、并集和差集的时候,两个容器都必须是有序序列。

set_intersection();   //求两个容器的交集
set_union();  //求两个容器的并集
set_difference();  //求两个容器的差集
  • 1
  • 2
  • 3

(1) set_intersection 求交集

set_intersection用来求两个容器的交集,两个容器都必须是有序序列,其函数原型如下。

set_intersection(iterator begin1,iterator end1,iterator begin2,iterator end2,iterator dest);
  • 1

set_intersection的返回值是目标容器最后一个元素指向的下一个迭代器位置,因此在打印的时候,结束迭代器的位置应选择该返回的迭代器。
关于set_intersection的应用示例代码如下。

#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>
using namespace std;

void fun()
{
	vector<int> v1,v2,v;
	for(int i=0;i<10;i++)
	{
		v1.push_back(i);  //0-9
		v2.push_back(i+5);  //5-14
	}
	v.resize(min(v1.size(),v2.size()));  //目标容器的尺寸取两个容器中的较小者的大小
	vector<int>::iterator end = set_intersection(v1.begin(),v1.end(),v2.begin(),v2.end(),v.begin());
	for(vector<int>::iterator i=v.begin();i!=end;i++)  //注意这里迭代器位置的设置
	{
		cout<<*i<<" ";
	}
	cout<<endl;
}

int main()
{
	fun();
	system("pause");
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

输出结果就是两个容器的交集。

(2) set_union 求并集

set_union用来求两个容器的并集,两个容器都必须是有序序列,其函数原型如下。

set_union(iterator begin1,iterator end1,iterator begin2,iterator end2,iterator dest);
  • 1

set_union的返回值是目标容器最后一个元素指向的下一个迭代器位置,因此在打印的时候,结束迭代器的位置应选择该返回的迭代器。
关于set_union的应用示例代码如下。

void fun()
{
	vector<int> v1,v2,v;
	for(int i=0;i<10;i++)
	{
		v1.push_back(i);
		v2.push_back(i+5);
	}
	v.resize(v1.size()+v2.size());  //目标容器的大小设置为两个容器大小之和
	vector<int>::iterator end = set_union(v1.begin(),v1.end(),v2.begin(),v2.end(),v.begin());
	for(vector<int>::iterator i=v.begin();i!=end;i++)  //注意这里迭代器位置的设置
	{
		cout<<*i<<" ";
	}
	cout<<endl;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

(3) set_difference 求差集

差集就是本容器中不是两个容器的交集部分,容器各自的交集一般是不同的。
set_difference用来求两个容器的差集,两个容器都必须是有序序列,其函数原型如下。

set_difference(iterator begin1,iterator end1,iterator begin2,iterator end2,iterator dest);
  • 1

关于set_difference的应用示例代码如下。

#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>
using namespace std;

void fun()
{
	vector<int> v1,v2,v12,v21;
	for(int i=0;i<10;i++)
	{
		v1.push_back(i);
		v2.push_back(i+5);
	}
	v12.resize(max(v1.size(),v2.size()));   //目标容器的尺寸取两个容器中的较大者的大小
	v21.resize(max(v1.size(),v2.size()));
	vector<int>::iterator end1 = set_difference(v1.begin(),v1.end(),v2.begin(),v2.end(),v12.begin());
	cout<<"v1和v2的差集: ";
	for(vector<int>::iterator i=v12.begin();i!=end1;i++)  //注意这里迭代器位置的设置
	{
		cout<<*i<<" ";
	}
	cout<<endl;
	vector<int>::iterator end2 = set_difference(v2.begin(),v2.end(),v1.begin(),v1.end(),v21.begin());
	cout<<"v2和v1的差集: ";
	for(vector<int>::iterator i=v21.begin();i!=end2;i++)
	{
		cout<<*i<<" ";
	}
	cout<<endl;
}

int main()
{
	fun();
	system("pause");
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

上面程序的运行结果如下图所示。
在这里插入图片描述


本文参考视频:
黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/222209
推荐阅读
相关标签
  

闽ICP备14008679号