C++笔记十一(STL:函数对象、常用算法)

1.STL——函数对象

1.1 函数对象概念
1> 重载函数调用操作符的类,其对象被称为函数对象。
2> 函数对象使用重载的()时,行为类似函数调用,也叫仿函数。

本质:函数对象(仿函数)是一个类,不是一个函数。

1.2 函数对象使用
特点:
1> 函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值。
2> 函数对象存超出普通函数的概念,函数对象可以有自己的状态。
3> 函数对象可以作为参数传递。

class MyAdd
{
    
    
public:
	int operator()(int a, int b)
	{
    
    
		return a + b;
	}
};
class MyPrintf
{
    
    
public:
	MyPrintf()
	{
    
    
		this->count = 0;
	}
	void operator()(string str)
	{
    
    
		cout << str << endl;
		count++;
	}
	int count;	//记录调用多少次
};
void test37(MyPrintf &p, string str)
{
    
    
	p(str);
}
void test36()
{
    
    
	MyAdd add;
	//函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值。
	cout << "3+5=" << add(3, 5) << endl;
	MyPrintf myprintf;
	myprintf("hello c++");
	myprintf("hello c++");
	myprintf("hello c++");
	//函数对象存超出普通函数的概念,函数对象可以有自己的状态。
	cout << "myprintf调用了" << myprintf.count << "次!" << endl;
	//函数对象可以作为参数传递。
	test37(myprintf, "hello world!");
}

1.3谓词概念
1> 返回bool类型的仿函数称为谓词。
2> 如果operator()接受一个参数,那么叫做一元谓词。
3> 如果operator()接受两个参数,那么叫做二元谓词。

一元谓词

class GreaterThree
{
    
    
public:
	bool operator()(int a)
	{
    
    
		return a > 3;
	}
};

void test38()
{
    
    
	vector<int> v;
	for (int i = 0; i < 5; i++)
	{
    
    
		v.push_back(i);
	}
	//GreaterThree()匿名对象
	vector<int>::iterator it = find_if(v.begin(), v.end(), GreaterThree());
	if(it!=v.end())
	{
    
    
		cout << "找到比三大的数!" << endl;
	}
}

二元谓词

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

void test39()
{
    
    
	vector<int> v;
	v.push_back(8);
	v.push_back(2);
	v.push_back(5);
	v.push_back(1);
	v.push_back(9);
	cout << "v:";
	VecPrintf(v);	//该函数在vector那一节里面实现过
	cout << "从小到大!";
	sort(v.begin(), v.end());
	cout << "v:";
	VecPrintf(v);
	cout << "从大到小!";
	sort(v.begin(), v.end(), MyComp());
	cout << "v:";
	VecPrintf(v);
}

1.4内建函数对象
概念:STL内建了一些函数对象。

分类:
1> 算术仿函数
2> 关系仿函数
3> 逻辑仿函数

用法:
1> 这些仿函数所产生的对象,用法和一般函数完全相同
2>使用内建函数对象,需要引入头文件#include< functional >

1.5 算术仿函数:
功能:实现四则运算,其中negate是一元运算,其他为二元运算。

仿函数的函数原型:
1> template< class T> T plus< T > //加法仿函数
2> template< class T> T minus< T > //减法仿函数
3> template< class T> T multiplies< T > //乘法仿函数
4> template< class T> T divides< T > //除法仿函数
5> template< class T> T modulus< T > //取模仿函数
6> template< class T> T negate< T > //取反仿函数

void test40()
{
    
    
	plus<int> p;
	cout << "5+8=" << p(5, 8) << endl;
	negate<int> n;
	cout << "给6取反:" << n(6) << endl;
}

1.6关系仿函数
功能:实现关系对比

仿函数原型:
1> tempalte< class T > bool equal_to < T > //等于
2> template< class T > bool not_equal_to< T > //不等于
3> template< class T > bool greater< T > //大于
4> tempalte< class T > bool greater_equal< T > //大于等于
5> template< class T > bool less< T > //小于
6> template< class T > bool less_equal< T > //小于等于
其中大于用的最多

void test41()
{
    
    
	vector<int> v;
	v.push_back(8);
	v.push_back(2);
	v.push_back(5);
	v.push_back(1);
	v.push_back(9);
	cout << "v:";
	VecPrintf(v);	//该函数在vector那一节里面实现过
	cout << "从小到大!";
	sort(v.begin(), v.end());
	cout << "v:";
	VecPrintf(v);
	cout << "从大到小!";
	sort(v.begin(), v.end(), greater<int>());
	cout << "v:";
	VecPrintf(v);
}

1.7 逻辑仿函数
功能:实现逻辑运算

仿函数原型:
1> template< class T > bool logical_and< T > //逻辑与
2> template< class T > bool logical_or< T > //逻辑或
3> template< class T > bool logical_not< T > //逻辑非
基本上用不到

void test42()
{
    
    
	vector<bool> v;
	v.push_back(true);
	v.push_back(false);
	v.push_back(false);
	v.push_back(true);
	v.push_back(false);
	cout << "V:";
	for (vector<bool>::iterator it = v.begin(); it != v.end(); it++)
	{
    
    
		cout << *it;
	}
	cout << endl;
	vector<bool> v1;
	//必须要先给v1开辟空间,不然transform无法将v的元素搬运到v1
	v1.resize(v.size());	
	transform(v.begin(), v.end(), v1.begin(), logical_not<bool>());
	cout << "V1:";
	for (vector<bool>::iterator it = v1.begin(); it != v1.end(); it++)
	{
    
    
		cout << *it;
	}
}

2.STL——常用算法

2.1 概述:
1> 算法主要是由头文件< algorithm >、< functional >、< numeric >组成。
2> < algorithm >是所有STL头文件中最大的一个,范围涉及到比较、交换、查找、遍历操作、复制、修改等等。
3> < numeric >体积很小,只包括几个在序列上面进行简单数学运算的模板函数。
4> < functional > 定义了一些模板类,用以声明函数对象。

2.2 常用遍历算法
目标:掌握常用的遍历算法。
1> for_each
2> transform
注意:for_each后面用函数名与函数对象都可以

算法简介:
1> for_each //遍历容器 (非常常用,必须掌握

class MyPrintf
{
    
    
public:
	void operator()(int a)
	{
    
    
		cout << a << "  ";
	}
};
void print(int a)
{
    
    
	cout << a << "  ";
}
void test()
{
    
    
	vector<int> v(6, 8);
	//使用普通函数
	for_each(v.begin(), v.end(), print);
	cout << endl;
	//使用仿函数
	for_each(v.begin(), v.end(), MyPrintf());
	cout << endl;
}

2> transform
功能:搬运容器到另一个容器中。

函数原型:
transform(iterator beg1, iterator end1, iterator beg2, _func)
//beg1 源容器开始迭代器
//end1 原容器结束迭代器
//beg2 目标容器开始迭代器
//_func 函数或者函数对象

注意:_func函数名或者函数对象都可以,而且for_each也是如此。至于前面用到过加法函数对象里面有参数是因为,先创建了对象,对象后面跟的参数是重载(),相当于函数了。这里是使用的类名()就是使用匿名对象,即使重载()里有参数这里也不写参数,这里是创建函数对象,相当于普通函数的函数名,所以无论是for_each还是transform后面写函数对象与写普通函数的函数名效果一样。

void print(int a)
{
    
    
	cout << a << "  ";
}
class Trans
{
    
    
public:
	int operator()(int v)	
	{
    
    
		return v+10;
	}
};
int Transform(int v)
{
    
    
	return v+10;
}
void test1()
{
    
    
	vector<int> v;	//源容器
	cout << "v:";
	for (int i = 0; i < 5; i++)
	{
    
    
		v.push_back(i);
	}
	for_each(v.begin(), v.end(), print);
	cout << endl;
	vector<int> v1;	//目标容器
	v1.resize(v.size());
	//这里Trans()里面没填参数是因为这里是函数对象,使用匿名对象
	//简单说,把构造函数、重载()操作符、成员函数、函数对象等理清即可
	transform(v.begin(), v.end(), v1.begin(), Trans());	
	cout << "v1:";
	for_each(v1.begin(), v1.end(), print);
	cout << endl;
	vector<int> v2;
	v2.resize(v.size());
	//这里Trans()与Transform效果一样,后者是函数名,前者是函数对象,需要理清楚
	transform(v1.begin(), v1.end(), v2.begin(), Transform);
	cout << "v2:";
	for_each(v2.begin(), v2.end(), print);
	cout << endl;
}

2.3 常用查找算法
目标:掌握常用的查找算法
算法简介:
1> find //查找元素
2> find_if //按照条件查找元素
3> adjacent_find //查找相邻重复元素
4> binary_search //二分查找
5> count //统计元素个数
6> count_if //按照条件统计元素个数

1> find
功能:查找指定元素,找到返回指向该元素的指针,找不到返回结束迭代器end()。
函数原型:
find(iterator beg, iterator end, value);

void print(int a)
{
    
    
	cout << a << "  ";
}
//使用find查找自定义数据类型
class Person
{
    
    
public:
	Person(string name, int age) :m_Name(name), m_Age(age) {
    
    }
	bool operator==(const Person &p)
	{
    
    
		if (this->m_Age == p.m_Age&&this->m_Name == p.m_Name)
		{
    
    
			return true;
		}
		else
		{
    
    
			return false;
		}
	}
	string m_Name;
	int m_Age;
};
//print1函数用于输出Person
void print1(const Person &p)
{
    
    
	cout << "姓名:" << p.m_Name << "  年龄:" << p.m_Age << endl;
}
void test()
{
    
    
	vector<int> v;
	for (int i = 0; i < 5; i++)
	{
    
    
		v.push_back(i);
	}
	cout << "v:";
	for_each(v.begin(), v.end(), print);
	cout << endl;
	//查找元素3
	vector<int>::iterator it = find(v.begin(), v.end(), 3);
	if (it != v.end())
	{
    
    
		cout << "找到元素3!" << endl;
	}
	else
	{
    
    
		cout << "找不到元素3" << endl;
	}

	cout << "使用find查找自定义数据类型!" << endl;
	string PartName = "abcde";
	vector<Person> v1;
	for (int i = 0; i < 3; i++)
	{
    
    
		string name = "Person ";
		name += PartName[i];
		int age = 15;
		age += i;
		Person p(name, age);
		v1.push_back(p);
	}
	cout << "v1:" << endl;
	for_each(v1.begin(), v1.end(), print1);
	Person p0("Person j", 15);
	//查找元素p
	//运行报错,通过看find函数的定义我们发现底层判断是*__first == __value_;很显然自定义数据数据类型无法直接比较
	//所以Person需要重载==操作符
	vector<Person>::iterator pit = find(v1.begin(), v1.end(), p0);
	if (pit == v1.end())
	{
    
    
		cout << "找不到元素p!" << endl;
	}
	else
	{
    
    
		cout << "找到元素p" << "  姓名为:" << pit->m_Name << "  年龄为:" << pit->m_Age << endl;
	}
}

值得注意的是如果查找的是自定义数据类型,需要重载== 操作符,具体要看函数定义。通过看find函数的定义我们发现底层判断是 (*__first) == __value _;很显然自定义数据数据类型无法直接比较。所以Person需要重载==操作符

2>find_if
功能:按条件查找元素

函数原型:
find_if(iterator beg, iterator end, _Pred);
//按照条件查找元素,找到返回指定位置的迭代器,找不到返回结束迭代器位置
//beg开始迭代器
//end结束迭代器
//_Pred 函数名或者谓词(返回bool类型的仿函数)

class GreaterFive
{
    
    
public:
	bool operator()(int v)
	{
    
    
		return v > 5;
	}
};
void test()
{
    
    
	vector<int> v;
	for (int i = 0; i < 5; i++)
	{
    
    
		v.push_back(i);
	}
	vector<int>::iterator it = find_if(v.begin(), v.end(), GreaterFive());
	if (it == v.end())
	{
    
    
		cout << "找不到大于5的元素!" << endl;
	}
	else
	{
    
    
		cout << "找到大于5的元素!" << endl;
	}
}

//find_if 自定义类型
class Person
{
    
    
public:
	Person(string name, int age) :m_Name(name), m_Age(age) {
    
    }
	string m_Name;
	int m_Age;
};
class FindAge
{
    
    
public:
	bool operator()(const Person &p)
	{
    
    
		return p.m_Age == 16;
	}
};
void test1()
{
    
    
	vector<Person> v;
	string PartName = "ABCDE";
	for (int i = 0; i < 5; i++)
	{
    
    
		string name = "Student";
		name += PartName[i];
		int age = 15 + i;
		Person p(name, age);
		v.push_back(p);
	}
	cout << "查找年龄为16的学生!" << endl;
	vector<Person>::iterator it = find_if(v.begin(), v.end(), FindAge());
	if (it == v.end())
	{
    
    
		cout << "没找到!" << endl;
	}
	else
	{
    
    
		cout << "找到了,姓名为:" << it->m_Name << endl;
	}
}

3> adjacent_find
功能:查找相邻重复元素

函数原型:
adjacent_find(iterator beg, iterator end);
//查找相邻重复元素,返回相邻元素的第一个位置的迭代器
//beg 开始迭代器
//end 结束迭代器

注意:一般实际开发中用的不多,可能面试会用到。

void test()
{
    
    
	vector<int> v;
	v.push_back(0);
	v.push_back(3);
	v.push_back(0);
	v.push_back(7);
	v.push_back(5);
	v.push_back(5);
	v.push_back(8);

	vector<int>::iterator it = adjacent_find(v.begin(), v.end());
	cout << "v中第一个重复元素为:" << *it << endl;
}

4> binary_search
功能:查找指定元素是否存在

函数原型:bool binary_search(iterator beg, iterator end, value);
//查找指定的元素,找到返回ture,否则返回false。
//beg开始迭代器
//end结束迭代器
//value 查找的元素

注意:无序序列中不可使用

void test()
{
    
    
	vector<int> v;
	for (int i = 0; i < 10; i++)
	{
    
    
		v.push_back(i);
	}
	if (binary_search(v.begin(), v.end(), 8))
	{
    
    
		cout << "找到元素8" << endl;
	}
	else
	{
    
    
		cout << "没找到元素8" << endl;
	}
}

5> count
功能:统计元素个数
函数原型:
count(iterator beg, iterator end, value);
//统计元素出现的次数
//beg开始迭代器
//end结束迭代器
//value统计的元素
//统计内置数据类型

注意:如果要对自定义数据类型的容器进行计数便要重载==,与前面一致,还是去看看count函数的底层实现,发现依然用到了 ==进行比较。

void test()
{
    
    
	vector<int> v;
	v.push_back(0);
	v.push_back(3);
	v.push_back(0);
	v.push_back(7);
	v.push_back(5);
	v.push_back(5);
	v.push_back(8);
	cout << "元素0出现次数:" << count(v.begin(), v.end(), 0) << endl;
}
//统计自定义数据类型
class Person
{
    
    
public:
	Person(string name, int age) :m_Name(name), m_Age(age) {
    
    }
	bool operator==(const Person &p)
	{
    
    
		if (this->m_Age == p.m_Age)
		{
    
    
			return true;
		}
		else
		{
    
    
			return false;
		}
	}
	string m_Name;
	int m_Age;
};

void test1()
{
    
    
	vector<Person> v;
	Person p1("张三", 16);
	Person p2("李四", 16);
	Person p3("王五", 17);
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	int num = count(v.begin(), v.end(), p2);
	cout << "与李四同岁的一共有" << num << "人!" << endl;
}

6> count_if
功能:按条件统计元素个数
函数原型:
count_if(iterator beg, iterator end, _Pred);
//按条件统计元素出现次数
//beg开始迭代器
//end结束迭代器
//_Pred 谓词或者普通函数函数名

class GreaterTwo
{
    
    
public:
	bool operator()(int v)
	{
    
    
		return v > 2;
	}
};
bool greaterTwo(int v)
{
    
    
	return v > 2;
}
void test()
{
    
    
	vector<int> v;
	for (int i = 0; i < 5; i++)
	{
    
    
		v.push_back(i);
	}
	int num = count_if(v.begin(), v.end(), greaterTwo);
	cout << "大于2的有:" << num << "个" << endl;
}

class Person
{
    
    
public:
	Person(string name, int age) :m_Name(name), m_Age(age) {
    
    }
	string m_Name;
	int m_Age;
};
class AgeGreater17
{
    
    
public:
	bool operator ()(const Person &p)
	{
    
    
		return p.m_Age > 17;
	}
};
bool ageGreater16(const Person &p)
{
    
    
	return p.m_Age > 16;
}
void test1()
{
    
    
	vector<Person> v;
	Person p1("张三", 16);
	Person p2("李四", 16);
	Person p3("王五", 17);
	Person p4("张飞", 19);
	Person p5("刘备", 18);
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);
	v.push_back(p5);
	int num = count_if(v.begin(), v.end(), ageGreater16);
	cout << "年龄大于16有" << num << "人" << endl;
}

2.4 常用排序算法
目标:掌握常用的排序算法
算法简介:
1> sort; //对容器内的元素进行排序
2>random_shuffle;//洗牌,指定范围内的元素随机调整次序
3>merge;//容器元素合并,并存储到同一容器中
4>reverse; //反转指定范围的元素

1> sort
功能描述:对容器内元素进行排序
函数原型:
sort(iterator beg, iterator end, _Pred);
//按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器
//beg 开始迭代器
//end 结束迭代器
//_Pred 谓词或者普通函数函数名

void print(int v)
{
    
    
	cout << v << "  ";
}
void test()
{
    
    
	vector<int> v;
	for (int i = 10; i > 0; i--)
	{
    
    
		v.push_back(i);
	}
	cout << "V:";
	for_each(v.begin(), v.end(), print);
	//这里sort默认升序排列,如果加入一些STL内建的函数对象,比如greater<int>()
	//template< class T > bool greater< T >	//大于
	sort(v.begin(), v.end());	
	cout << "使用sort排序后!" << endl;
	cout << "V:";
	for_each(v.begin(), v.end(), print);
}

注意:sort是开发中最常用的算法之一,必须掌握

2> random_shuffle
功能:洗牌,指定范围内的元素随机调整次序
函数原型:
random_shuffle(iterator beg, iterator end);
//指定范围内的元素进行随机调整次序
//beg 开始迭代器
//end 结束迭代器

void print(int v)
{
    
    
	cout << v << "  ";
}
void test()
{
    
    
	vector<int> v;
	for (int i = 10; i > 0; i--)
	{
    
    
		v.push_back(i);
	}
	cout << "V:";
	for_each(v.begin(), v.end(), print);
	cout << endl;
	random_shuffle(v.begin(), v.end());
	cout << "使用random_shuffle打乱排序后!" << endl;
	cout << "V:";
	for_each(v.begin(), v.end(), print);
}

注意:random_shuffle洗牌算法还是比较实用的,使用时记得加上随机种子。

3> merge
功能:两个容器元素合并,并存储到另一个容器中。
注意:两元素必须有序(且都是升序),而且合并后依然有序,并且目标容器在合并前要resize
函数原型:
merge(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
//容器元素合并,并存储到另一个容器中
//beg1 容器1开始迭代器
//end1 容器1结束迭代器
//beg2 容器2开始迭代器
//end2 容器2结束迭代器
//dest 目标容器的开始迭代器

void print(int v)
{
    
    
	cout << v << "  ";
}
void test()
{
    
    
	vector<int> v1;
	for (int i = 0; i < 10; i++)
	{
    
    
		v1.push_back(i);
	}
	cout << "V1:";
	for_each(v1.begin(), v1.end(), print);
	cout << endl;

	vector<int> v2;
	for (int i = 5; i < 10; i++)
	{
    
    
		v2.push_back(i);
	}
	cout << "v2:";
	for_each(v2.begin(), v2.end(), print);
	cout << endl;

	cout << "使用merge合并排序后!" << endl;
	vector<int> v;
	v.resize(20);
	merge(v1.begin(), v1.end(), v2.begin(), v2.end(), v.begin());
	cout << "V:";
	for_each(v.begin(), v.end(), print);
}

4> reverse
功能:将容器内的元素进行反转。
函数原型:
reverse(iterator beg, iterator end);
//反转指定范围内的元素
//beg 开始迭代器
//end 结束迭代器

void print(int v)
{
    
    
    cout<<v<<"  ";
}
void test()
{
    
    
    vector<int> v;
    for(int i = 0;i<10;i++)
    {
    
    
        v.push_back(i);
    }
    cout<<"v:";
    for_each(v.begin(), v.end(), print);
    cout<<"使用reverse反转后!"<<endl;
    reverse(v.begin(), v.end());
    cout<<"v:";
    for_each(v.begin(), v.end(), print);
}

2.5 常用拷贝和替换算法
目的:学习掌握拷贝和替换算法
算法简介:
1> copy 容器内指定范围内的元素拷贝到另一个容器中
2> replace 将容器内指定范围的旧元素修改成新元素
3> replace_if 将容器内指定范围内的符合条件的旧元素修改成新元素
4> swap 互换两容器内的元素

1> copy
功能:将容器内指定范围的元素拷贝到另一个容器中
函数原型:
copy(iterator beg, iterator end, iterator dest);
//将容器内指定范围内的元素拷贝到另一个容器中
//beg:开始迭代器
//end:结束迭代器
//dest:目标迭代器的开始迭代器

注意:这里使用copy之前对目标容器要使用resize函数开辟空间,此函数一般实际开发中使用不多。

void print(int i)
{
    
    
    cout<<i<<"  ";
}
void test()
{
    
    
    vector<int> v;
    for(int i=0;i<10;i++)
    {
    
    
        v.push_back(i);
    }
    cout<<"v:";
    for_each(v.begin(), v.end(), print);
    cout<<endl;
    cout<<"v1使用copy,复制v!"<<endl;
    vector<int> v1;
    v1.resize(10);
    copy(v.begin(), v.end(), v1.begin());
    cout<<"v1:";
    for_each(v1.begin(), v1.end(), print);
    cout<<endl;
}

2> replace
功能:将容器内指定范围内的元素替换成新元素
函数原型:
replace(iterator beg, iterator end, oldvalue, newvalue);
//指定范围内的元素替换成新元素
//beg 开始迭代器
//end 结束迭代器
//oldvalue 旧元素
//newvalue 新元素

void print(int i)
{
    
    
    cout<<i<<"  ";
}
void test()
{
    
    
    vector<int> v;
    for(int i=0;i<10;i++)
    {
    
    
        v.push_back(i);
    }
    cout<<"v:";
    for_each(v.begin(), v.end(), print);
    cout<<endl;
    cout<<"把5替换成35"<<endl;
    replace(v.begin(), v.end(), 5, 35);
    cout<<"v:";
    for_each(v.begin(), v.end(), print);
    cout<<endl;
}

3> replace_if
功能:将容器内指定范围内的所有符合条件的元素替换成新元素
函数原型:
replace_if(iterator beg, iterator end, _ Pred, newvalue);
//把范围内所有符合条件的元素用新元素替换
//beg 开始迭代器
//end 结束迭代器
//_ Pred 谓词或者函数名
//newvalue 替换的新元素

void print(int i)
{
    
    
    cout<<i<<"  ";
}
bool Greater5(int a)
{
    
    
    return a>5;
}
void test()
{
    
    
    vector<int> v;
    for(int i=0;i<10;i++)
    {
    
    
        v.push_back(i);
    }
    cout<<"v:";
    for_each(v.begin(), v.end(), print);
    cout<<endl;
    cout<<"把大于5的都替换成30"<<endl;
    replace_if(v.begin(), v.end(), Greater5, 30);
    cout<<"v:";
    for_each(v.begin(), v.end(), print);
    cout<<endl;
}

4>swap
功能:互换两容器的元素
注意:一定要两种同等类型的容器
函数原型:
swap(container c1, container c2);
//互换两容器的元素
//c1,容器1
//c2,容器2

void print(int i)
{
    
    
    cout<<i<<"  ";
}
void test()
{
    
    
    vector<int> v1;
    vector<int> v2;
    for(int i=0;i<10;i++)
    {
    
    
        v1.push_back(i);
        v2.push_back(i+5);
    }
    cout<<"v1:";
    for_each(v1.begin(), v1.end(), print);
    cout<<endl;
    cout<<"v2:";
    for_each(v2.begin(), v2.end(), print);
    cout<<endl;
    cout<<"使用swap交换后!"<<endl;
    swap(v1, v2);
    cout<<"v1:";
    for_each(v1.begin(), v1.end(), print);
    cout<<endl;
    cout<<"v2:";
    for_each(v2.begin(), v2.end(), print);
    cout<<endl;
}

2.6 常用算术生成算法
目标:学习掌握常用的算术生成算法。

注意:算术生成算法属于小型算法,使用需要包含头文件#include< numeric >

算法简介:
1> accumulate; 计算容器元素累计总和
2> fill; //向容器中添加新元素

1> accumulate
功能:计算区间内容器元素累计总和
函数原型:
accumulate(iterator beg, iterator end, value);
//计算区间内容器元素累计总和
//beg 开始迭代器
//end 结束迭代器
//value 起始值

void print(int i)
{
    
    
    cout<<i<<"  ";
}
void test()
{
    
    
    vector<int> v;
    for(int i=0;i<10;i++)
    {
    
    
        v.push_back(i);
    }
    cout<<"v:";
    for_each(v.begin(), v.end(), print);
    cout<<endl;
    cout<<"元素总和为:";
    int total = accumulate(v.begin(), v.end(), 0);
    cout<<total<<endl;
}

该算法比较常用

2> fill
功能:向容器中添加新元素。

注意:这里的填充,即使区间内有初始值也被换成填充值。

函数原型:
fill(iterator beg, iterator end, value);
//向容器中添加新元素
//beg 开始迭代器
//end 结束迭代器
//value 填充的值

void print(int i)
{
    
    
    cout<<i<<"  ";
}
void test()
{
    
    
    vector<int> v;
    for(int i=0;i<10;i++)
    {
    
    
        v.push_back(i);
    }
    v.resize(15);
    fill(v.begin(), v.end(), 100);
    cout<<"v:";
    for_each(v.begin(), v.end(), print);
    cout<<endl;
    //v:100  100  100  100  100  100  100  100  100  100  100  100  100  100  100 
}

2.7 常用集合算法
目标:掌握常用的集合算法
算法简介:
1> set_intersection //求两个容器的交集
2> set_union //求两个容器的并集
3> set_difference //求两个容器的差集

1> set_intersection
功能:求两个容器的交集
函数原型:
set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
注意:返回的是指向交集最后一个元素的下一位的迭代器
//求两个容器的交集
//beg1 容器1开始迭代器
//end1 容器1结束迭代器
//beg2 容器2开始迭代器
//end2 容器2结束迭代器
//dest 目标容器的开始迭代器

void print(int v)
{
    
    
	cout << v << "  ";
}
void test()
{
    
    
	vector<int> v1;
	for (int i = 0; i < 10; i++)
	{
    
    
		v1.push_back(i);
	}
	cout << "V1:";
	for_each(v1.begin(), v1.end(), print);
	cout << endl;

	vector<int> v2;
	for (int i = 5; i < 15; i++)
	{
    
    
		v2.push_back(i);
	}
	cout << "v2:";
	for_each(v2.begin(), v2.end(), print);
	cout << endl;

	cout << "使用set_intersection求交集后!" << endl;
	vector<int> v;
	v.resize(min(v1.size(),v2.size()));
	vector<int>::iterator it = set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), v.begin());
	cout << "V:";
	//这里如果使用end的话,便会把所有元素都输出出来,显然容器的大小是大于等于交集大小的,那剩余部分由0填充。
	//for_each(v.begin(), v.end(), print);
	//cout << endl;
	for_each(v.begin(), it, print);
}

2> set_union
功能:求两个集合的并集
注意:两个集合必须是有序序列,必须是升序
函数原型:
set_union(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
//求两个集合的并集
//beg1 容器1开始迭代器
//end1 容器1结束迭代器
//beg2 容器2开始迭代器
//end2 容器2结束迭代器
//dest 目标容器的开始迭代器

void print(int v)
{
    
    
	cout << v << "  ";
}
void test()
{
    
    
	vector<int> v1;
	for (int i = 0; i < 10; i++)
	{
    
    
		v1.push_back(i);
	}
	cout << "V1:";
	for_each(v1.begin(), v1.end(), print);
	cout << endl;

	vector<int> v2;
	for (int i = 5; i < 15; i++)
	{
    
    
		v2.push_back(i);
	}
	cout << "v2:";
	for_each(v2.begin(), v2.end(), print);
	cout << endl;

	cout << "使用set_union求并集后!" << endl;
	vector<int> v;
	v.resize(v1.size()+v2.size());
	vector<int>::iterator it = set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), v.begin());
	cout << "V:";
	//这里如果使用end的话,便会把所有元素都输出出来,显然容器的大小是大于等于交集大小的,那剩余部分由0填充。
	//for_each(v.begin(), v.end(), print);
	//cout << endl;
	for_each(v.begin(), it, print);
}

3> set_difference
注意:这里哪个容器在前就在哪个容器的基础上求差集。例如v1{1,2,3} v2{3,4,5}如果v1在前求出便是v{1,2},反之v{4,5}.所以这里关于目标容器的大小就直接按照max(v1.size(), v2.size())
函数原型:
set_difference(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
//求v1和v2的差集
//beg1 容器v1开始迭代器
//end1 容器v1结束迭代器
//beg2 容器v2开始迭代器
//end2 容器v2结束迭代器
//dest 目标容器的开始迭代器

void print(int v)
{
    
    
	cout << v << "  ";
}
void test()
{
    
    
	vector<int> v1;
	for (int i = 0; i < 10; i++)
	{
    
    
		v1.push_back(i);
	}
	cout << "V1:";
	for_each(v1.begin(), v1.end(), print);
	cout << endl;

	vector<int> v2;
	for (int i = 5; i < 15; i++)
	{
    
    
		v2.push_back(i);
	}
	cout << "v2:";
	for_each(v2.begin(), v2.end(), print);
	cout << endl;

	cout << "使用set_difference求交集后!" << endl;
	vector<int> v3;
	v3.resize(max(v1.size(), v2.size()));
	vector<int>::iterator it1 = set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());
	cout << "v1和v2的差集:";
	//这里如果使用end的话,便会把所有元素都输出出来,显然容器的大小是大于等于交集大小的,那剩余部分由0填充。
	//for_each(v.begin(), v.end(), print);
	//cout << endl;
	for_each(v3.begin(), it1, print);
	cout << endl;
	vector<int> v4;
	v4.resize(max(v1.size(), v2.size()));
	vector<int>::iterator it2 = set_difference(v2.begin(), v2.end(), v1.begin(), v1.end(), v4.begin());
	cout << "v2和v1的差集:";
	//这里如果使用end的话,便会把所有元素都输出出来,显然容器的大小是大于等于交集大小的,那剩余部分由0填充。
	//for_each(v.begin(), v.end(), print);
	//cout << endl;
	for_each(v4.begin(), it2, print);
}

猜你喜欢

转载自blog.csdn.net/weixin_45884870/article/details/111414127