STL基础梳理 2019.1.19(仿函数,谓词,内建函数对象,适配器,算法)

常用算法

 

函数对象(也叫仿函数)

重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象,也叫仿函数(functor),其实就是重载“()”操作符,使得类对象可以像函数那样调用。

注意:

1.函数对象(仿函数)是一个类,不是一个函数。

2.函数对象(仿函数)重载了”() ”操作符使得它可以像函数一样调用。

分类:

假定某个类有一个重载的operator(),而且重载的operator()要求获取一个参数,我们就将这个类称为一元仿函数”(unary functor);相反,如果重载的operator()要求获取两个参数,就将这个类称为二元仿函数”(binary functor)

函数对象的作用主要是什么?STL提供的算法往往都有两个版本,其中一个版本表现出最常用的某种运算,另一版本则允许用户通过template参数的形式来指定所要采取的策略。

 

仿函数的两种调用方式

class MyPrint{
public:
	void operator()( int num){
		cout << "num " << num << endl;
		count++;
	}
	int count = 0;
};

void test01(){
	//MyPrint是一个类 ,而不是函数
	MyPrint myPrint;
        //方式一
	myPrint(111); 
        //方式二
	MyPrint()(1000);
}

 

 

仿函数可以保存状态

函数对象超出普通函数概念,内部可以保存状态

class MyPrint{
public:
	void operator()( int num){
		cout << "num " << num << endl;
		count++;
	}
	int count = 0;
};

//函数对象超出普通函数概念,内部可以保存状态
void test02(){
	MyPrint myPrint;
	myPrint(111);
	myPrint(111);
	myPrint(111);
	myPrint(111);
	//输出4
	cout << "myPrint使用次数:" << myPrint.count << endl;
}

 

 

仿函数作为参数

class MyPrint{
public:
	void operator()( int num){
		cout << "num " << num << endl;
		count++;
	}
	int count = 0;
};

//函数对象作为参数
void doPrint(MyPrint print, int num){
	print(num);
}
void test03(){
	doPrint(MyPrint(), 20);
}

 

 

谓词

谓词是指普通函数重载的operator()返回值是bool类型的函数对象(仿函数)。

  • 如果operator接受一个参数,那么叫做一元谓词,
  • 如果接受两个参数,那么叫做二元谓词

 

使用示例:

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

class GreaterThen20{
public:
	bool operator()(int val){
		return val > 20;
	}
};

//一元谓词
void test01(){
	vector<int>v;
	v.push_back(10);
	v.push_back(20);
	v.push_back(30);
	v.push_back(40);
	v.push_back(50);

	//查找第一个大于20的数字  find_if 查找符合条件的值,返回值是一个迭代器
	//第三个参数 函数对象  匿名对象
	vector<int>::iterator pos = find_if(v.begin(), v.end(), GreaterThen20());
	if (pos!=v.end()){
		cout << "找到大于20的数字为:" << *pos << endl;
	}else{
		cout << "未找到" << endl;
	}
}

//二元谓词
class MyCompare{
public:
	bool operator()(int v1 ,int v2){
		return v1 > v2;
	}
};

void test02(){
	vector<int>v;
	v.push_back(10);
	v.push_back(20);
	v.push_back(30);
	v.push_back(40);
	v.push_back(50);

	sort(v.begin(), v.end(), MyCompare());

	//匿名函数  lambda表达式  [](){};
	for_each(v.begin(), v.end(), [](int val){ cout << val << " "; });
}

int main(){

        test01();
	test02();

	system("pause");
	return EXIT_SUCCESS;
}

 

 

lambda表达式  [](){};

匿名函数,[]是标识符,()放参数,{}是结构体

 

 

内建函数对象

 

STL内建了一些函数对象。分为:算数类函数对象,    关系运算类函数对象, 逻辑运算类仿函数。这些仿函数所产生的对象,用法和一般函数完全相同,当然我们还可以产生无名的临时对象来履行函数功能。使用内建函数对象,需要引入头文件

#include<functional>

 

6个算数类函数对象,除了negate是一元运算,其他都是二元运算。

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>//取反仿函数

 

6个关系运算类函数对象,每一种都是二元运算。

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>//小于等于

 

逻辑运算类运算函数,not为一元运算,其余为二元运算。

template<class T> bool logical_and<T>//逻辑与
template<class T> bool logical_or<T>//逻辑或
template<class T> bool logical_not<T>//逻辑非

 

使用示例

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
//内建函数对象头文件
#include <functional>
#include <vector>
#include <algorithm>
using namespace std;

void test01(){
	//template<class T> T negate<T>//取反仿函数
	negate<int>n;
	cout << n(10) << endl;//-10

	//加法  template<class T> T plus<T>//加法仿函数
	plus<int> p;
	cout << p(1, 1) << endl;
}

//template<class T> bool greater<T>//大于
void test02(){
	vector<int>v;

	v.push_back(10);
	v.push_back(30);
	v.push_back(50);
	v.push_back(20);
	v.push_back(40);

	sort(v.begin(), v.end(), greater<int>());
	for_each(v.begin(), v.end(), [](int val){ 
		cout << val << " "; });//50 40 30 20 10
}

int main(){
	test01();
	test02();
	system("pause");
	return EXIT_SUCCESS;
}

 

 

 

适配器

 

头文件

#include<functional>

 

bind2nd使用示例

我们希望仿函数的值可以与用户输入的值相加,而仿函数只有一个参数,因此使用适配器bind2nd来扩展端口。

原代码(不包含适配器)

class MyPrint{
public:
	void operator()(int v ) {
		cout << "v = "<< v << endl;
	}

};

void test01()
{
	vector<int>v;
	for (int i = 0; i < 10;i++)
	{
		v.push_back(i);
	}
	
	for_each(v.begin(), v.end(), MyPrint()) );
}

加上适配器之后

class MyPrint:public binary_function<int,int,void>
{
public:
	void operator()(int v ,int start) const
	{
		cout << "v = "<< v << " start = "<< start << " v+start = "<< v  + start<< endl;
	}

};

void test01()
{
	vector<int>v;
	for (int i = 0; i < 10;i++)
	{
		v.push_back(i);
	}
	cout << "请输入起始值" << endl;
	int num;
	cin >> num;

	//for_each(v.begin(), v.end(), bind2nd( MyPrint(),num) );
	for_each(v.begin(), v.end(), bind1st(MyPrint(), num));
}

添加适配器的步骤:

 1、绑定 数据 bind2nd

for_each(v.begin(), v.end(), bind2nd( MyPrint(),num) );

2、继承类 binary_function<参数类型1 ,参数类型2 ,返回值类型>

class MyPrint:public binary_function<int,int,void>

3、加const修饰 operator()

 

 

一元取反适配器  not1

查找大于5的值

class GreaterThenFive{
public:
	bool operator()(int v) {
		return v > 5;
	}
};

void test02(){
	vector<int>v;
	for (int i = 0; i < 10;i++){
		v.push_back(i);
	}

	//查找大于5的数字
	vector<int>::iterator pos =  find_if(v.begin(), v.end(), GreaterThenFive());
	if (pos!= v.end()){
		cout << "找到大于5的数字为 " << *pos << endl;
	}else{
		cout << "未找到" << endl;
	}
}

需求改为:查找小于5的值

class GreaterThenFive:public unary_function<int,bool>{
public:
	bool operator()(int v) const{
		return v > 5;
	}
};
//取反适配器
void test02(){
	//一元取反
	vector<int>v;
	for (int i = 0; i < 10;i++){
		v.push_back(i);
	}

	//查找大于5的数字
	//需求改为 找小于5的数字
	vector<int>::iterator pos =  find_if(v.begin(), v.end(), not1( GreaterThenFive()));
	if (pos!= v.end()){
		cout << "找到小于5的数字为 " << *pos << endl;
	}else{
		cout << "未找到" << endl;
	}
}

修改步骤:

1、一元取反适配器  not1

vector<int>::iterator pos =  find_if(v.begin(), v.end(), not1( GreaterThenFive()));

2、继承 unary_function <参数类型1,返回值类型>

class GreaterThenFive:public unary_function<int,bool>

3、加const修饰 operator()

 

也可以使用如下方法:

vector<int>::iterator pos = find_if(v.begin(), v.end(),  not1( bind2nd(greater<int>(),5) ));

 

函数指针适配器

将函数指针适配成函数对象,使其可以使用适配器。

源代码如下:

void MyPrint03(int v ) {
	cout << v  << endl;
}
//函数指针适配器
void test03(){
	vector<int>v;
	for (int i = 0; i < 10; i++){
		v.push_back(i);
	}
	//将函数指针 适配为 函数对象
	// ptr_fun
	for_each(v.begin(), v.end(),  MyPrint03);
}

修改后代码:

void MyPrint03(int v ,int start) {
	cout << v + start << endl;
}
//函数指针适配器
void test03(){
	vector<int>v;
	for (int i = 0; i < 10; i++){
		v.push_back(i);
	}
	//将函数指针 适配为 函数对象
	// ptr_fun
	for_each(v.begin(), v.end(), bind2nd( ptr_fun( MyPrint03) ,100 ));
}

好处在于不用加继承,也不用加const

 

成员函数适配器

成员函数适配

//如果容器存放的是对象指针, 用  
mem_fun

//如果容器中存放的是对象实体,用  
mem_fun_ref

修改前

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

	string m_Name;
	int m_Age;
};

void MyPrintPerson( Person & p){
	cout << "姓名: " << p.m_Name << " 年龄:" << p.m_Age << endl;
}

void test04()
{
	vector<Person>v;

	Person p1("aaa", 10);
	Person p2("bbb", 15);
	Person p3("ccc", 18);
	Person p4("ddd", 40);

	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);

	for_each(v.begin(), v.end(),  MyPrintPerson);	
}

使用成员函数的版本

class Person{
public:
	Person(string name, int age){
		this->m_Name = name;
		this->m_Age = age;
	}
	void showPerson(){
		cout << "成员函数中:姓名: " << m_Name << " 年龄:" << m_Age << endl;
	}
	
	string m_Name;
	int m_Age;
};


void test04(){
	vector<Person>v;

	Person p1("aaa", 10);
	Person p2("bbb", 15);
	Person p3("ccc", 18);
	Person p4("ddd", 40);

	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);

	//成员函数适配器
	// mem_fun_ref
	for_each(v.begin(), v.end(),  mem_fun_ref(&Person::showPerson));
}

 

 

 

算法

算法主要是由头文件<algorithm> <functional> <numeric>组成。

<algorithm>是所有STL头文件中最大的一个,其中常用的功能涉及到比较,交换,查找,遍历,复制,修改,反转,排序等...

<numeric>体积很小,只包括在几个序列容器上进行的简单运算的模板函数.

<functional> 定义了一些模板类,用以声明函数对象。

 

常用遍历算法

/*
    遍历算法 遍历容器元素
	@param beg 开始迭代器
	@param end 结束迭代器
	@param _callback  函数回调或者函数对象
	@return 函数对象
*/
for_each(iterator beg, iterator end, _callback);
/*
	transform算法 将指定容器区间元素搬运到另一容器中
	注意 : transform 不会给目标容器分配内存,所以需要我们提前分配好内存
	@param beg1 源容器开始迭代器
	@param end1 源容器结束迭代器
	@param beg2 目标容器开始迭代器
	@param _cakkback 回调函数或者函数对象
	@return 返回目标容器迭代器
*/
transform(iterator beg1, iterator end1, iterator beg2, _callbakc)

 

for_each

基本用法

使用示例1

void myPrint(int v){
	cout << v << endl;
}

void test01(){
	vector<int>v;
	for (int i = 0; i < 10;i++){
		v.push_back(i);
	}
	for_each(v.begin(), v.end(), myPrint);
}

使用示例2;

struct myPrint01{
	void operator()(int v){
		cout << v << endl;
	}
};

void test01(){
	vector<int>v;
	for (int i = 0; i < 10;i++){
		v.push_back(i);
	}
	for_each(v.begin(), v.end(), myPrint01());
}

 

 

for_each可以用来保存内部记录

for_each是有返回值的,返回值是类型对象

myPrint02 print2 = for_each(v.begin(), v.end(), myPrint02());

使用示例:

struct myPrint02{
	void operator()(int v){
		cout << v << endl;
		m_Count++;
	}
	int m_Count;
};
//2 for_each有返回值
void test02(){
	vector<int>v;
	for (int i = 0; i < 10; i++){
		v.push_back(i);
	}

	myPrint02 print2 = for_each(v.begin(), v.end(), myPrint02());
	cout << print2.m_Count << endl;
}

 

for_each可以绑定参数进行输出

//3 for_each可以绑定参数进行输出
struct myPrint03 :public binary_function<int,int,void>{
	void operator()(int v ,int start) const{
		cout << v  + start << endl;
	}
};

void test03(){
	vector<int>v;
	for (int i = 0; i < 10; i++){
		v.push_back(i);
	}
	for_each(v.begin(), v.end(), bind2nd(myPrint03(), 10000));
}

 

transform

transform算法 将指定容器区间元素搬运到另一容器中
注意 : transform 不会给目标容器分配内存,所以需要我们提前分配好内存
 

基本用法

class TransForm{
public:
	int operator()(int val){
		return val + 10;
	}
};
void test04(){
	vector<int>v; //原容器
	for (int i = 0; i < 10; i++){
		v.push_back(i);
	}
	vector<int>vTarget; //目标容器
	//分配内存
	vTarget.resize(v.size());
	transform(v.begin(), v.end(), vTarget.begin(), TransForm());
	for_each(vTarget.begin(), vTarget.end(), [](int val){ cout << val << " "; });
}

 

transform 第二种用法 将两个容器数据相加搬运到目标容器

//transform 第二种用法 将两个容器数据相加搬运到目标容器
class TransForm2{
public:
	int operator()(int val ,int val2){
		return val + val2;
	}
};

void test05(){
	vector<int>v1;
	vector<int>v2;
	for (int i = 0; i < 10;i++){
		v1.push_back(100 + i);
		v2.push_back(200 + i);
	}
	vector<int>vTarget; //目标容器
	vTarget.resize(v1.size());
	transform(v1.begin(), v1.end(), v2.begin(), vTarget.begin(), TransForm2());

	// 300 302...
	for_each(vTarget.begin(), vTarget.end(), [](int val){ 
		cout << val << " "; });
}

 

 

 

常用查找算法

/*
	find算法 查找元素
	@param beg 容器开始迭代器
	@param end 容器结束迭代器
	@param value 查找的元素
	@return 返回查找元素的位置
*/
find(iterator beg, iterator end, value)
/*
	find_if算法 条件查找
	@param beg 容器开始迭代器
	@param end 容器结束迭代器
	@param  callback 回调函数或者谓词(返回bool类型的函数对象)
	@return bool 查找返回true 否则false
*/
find_if(iterator beg, iterator end, _callback);

/*
	adjacent_find算法 查找相邻重复元素
	@param beg 容器开始迭代器
	@param end 容器结束迭代器
	@param  _callback 回调函数或者谓词(返回bool类型的函数对象)
	@return 返回相邻元素的第一个位置的迭代器
*/
adjacent_find(iterator beg, iterator end, _callback);
/*
	binary_search算法 二分查找法
	注意: 在无序序列中不可用
	@param beg 容器开始迭代器
	@param end 容器结束迭代器
	@param value 查找的元素
	@return bool 查找返回true 否则false
*/
bool binary_search(iterator beg, iterator end, value);
/*
	count算法 统计元素出现次数
	@param beg 容器开始迭代器
	@param end 容器结束迭代器
	@param  value回调函数或者谓词(返回bool类型的函数对象)
	@return int返回元素个数
*/
count(iterator beg, iterator end, value);
/*
	count算法 统计元素出现次数
	@param beg 容器开始迭代器
	@param end 容器结束迭代器
	@param  callback 回调函数或者谓词(返回bool类型的函数对象)
	@return int返回元素个数
*/
count_if(iterator beg, iterator end, _callback);

 

find

基本用法

void test01(){
	vector<int>v;
	for (int i = 0; i < 10;i++){
		v.push_back(i);
	}
	vector<int>::iterator pos = find(v.begin(), v.end(), 5);
	if (pos!=v.end()){
		cout << "找到了数据:" << *pos << endl;
	}else{
		cout << "未找到" << endl;
	}	
}

 

利用find查找自定义数据类型

class Person{
public:
	Person(string name, int age){
		this->m_Name = name;
		this->m_Age = age;
	}
	//重载 == ,不然find不知道如何做比较
	bool operator==( const Person&p){
		if (this->m_Name == p.m_Name && this->m_Age == p.m_Age){
			return true;
		}
		return false;
	}
	
	string m_Name;
	int m_Age;
};
//利用find查找自定义数据类型
void test02(){
	vector<Person>v;
	Person p1("aaa", 10);
	Person p2("bbb", 20);
	Person p3("ccc", 30);
	Person p4("ddd", 40);

	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);

	vector<Person>::iterator pos = find(v.begin(), v.end(), p2);	
	if (pos != v.end()){
		cout << "找到了数据姓名:" << (*pos).m_Name << " 年龄:" << pos->m_Age << endl;
	}else{
		cout << "未找到" << endl;
	}
}

 

find_if

class MyCompare :public binary_function<Person*, Person* ,bool>{
public:
	bool operator()( Person * p1 , Person * p2) const{
		if (p1->m_Name == p2->m_Name && p1->m_Age == p2->m_Age){
			return true;
		}
		return false;
	}
};

void test03(){
	vector<Person *>v;
	Person p1("aaa", 10);
	Person p2("bbb", 20);
	Person p3("ccc", 30);
	Person p4("ddd", 40);

	v.push_back(&p1);
	v.push_back(&p2);
	v.push_back(&p3);
	v.push_back(&p4);

	Person * p = new Person("bbb", 20);
	//find_if 
	//使用 bind2nd 绑定,这样就可以根据用户输入的信息来做对比
	vector<Person*>::iterator pos = find_if(v.begin(), v.end(),  bind2nd( MyCompare(), p));

	if (pos != v.end()){
		cout << "找到了数据姓名:" << (*pos)->m_Name << " 年龄:" << (*pos)->m_Age << endl;
	}else{
		cout << "未找到" << endl;
	}
}

 

adjacent_find算法 查找相邻重复元素

void test04(){
	vector<int>v;
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	v.push_back(5);
	v.push_back(6);
	v.push_back(2);

	vector<int>::iterator pos = adjacent_find(v.begin(), v.end());

	if (pos!= v.end()){
		cout << "找到了相邻重复元素为: " << *pos << endl;
	}else{
		cout << "未找到" << endl;
	}
}

 

binary_search算法 二分查找法

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

void test05(){
	vector<int>v;
	for (int i = 0; i < 10;i++){
		v.push_back(i);
	}
	
	bool ret =  binary_search(v.begin(), v.end(), 4);
	if (ret){
		cout << "找到了4" << endl;
	}else{
		cout << "未找到" << endl;
	}
}

 

count算法 count_if算法  统计元素出现次数 

class GreaterThenFour{
public:
	bool operator()(int v){
		return v >= 4;
	}
};
void test06(){	
	vector<int>v;
	for (int i = 0; i < 10; i++){
		v.push_back(i);
	}

	v.push_back(4);
	v.push_back(4);
	v.push_back(4);
	v.push_back(4);

	int num = count(v.begin(), v.end(), 4);
	cout << "4的个数为" << num << endl;

	num = count_if(v.begin(), v.end(), GreaterThenFour());
	cout << "大于等于 4的个数为" << num << endl;
}

 

 

 

常用排序算法

/*
	merge算法 容器元素合并,并存储到另一容器中
	@param beg1 容器1开始迭代器
	@param end1 容器1结束迭代器
	@param beg2 容器2开始迭代器
	@param end2 容器2结束迭代器
	@param dest  目标容器开始迭代器
*/
merge(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)
/*
	sort算法 容器元素排序
	注意:两个容器必须是有序的
	@param beg 容器1开始迭代器
	@param end 容器1结束迭代器
	@param _callback 回调函数或者谓词(返回bool类型的函数对象)
*/
sort(iterator beg, iterator end, _callback)
/*
	sort算法 对指定范围内的元素随机调整次序
	@param beg 容器开始迭代器
	@param end 容器结束迭代器
*/
random_shuffle(iterator beg, iterator end)
/*
	reverse算法 反转指定范围的元素
	@param beg 容器开始迭代器
	@param end 容器结束迭代器
*/
reverse(iterator beg, iterator end)

 

merge算法 容器元素合并,并存储到另一容器中  这两个容器 必须也是有序

void test01(){
	vector<int>v1;
	vector<int>v2;

	for (int i = 0; i < 10;i++){
		v1.push_back(i);
		v2.push_back(i + 1);
	}

	vector<int>vTarget;
	vTarget.resize(v1.size() + v2.size());
	merge(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
	for_each(vTarget.begin(), vTarget.end(), [](int v){ cout << v << " "; });
}

 

sort算法 容器元素排序

void test02(){
	vector<int>v1;

	v1.push_back(10);
	v1.push_back(40);
	v1.push_back(20);
	v1.push_back(90);
	v1.push_back(50);

	sort(v1.begin(), v1.end());
	for_each(v1.begin(), v1.end(), [](int val){cout << val << " "; });
	cout << endl;

	sort(v1.begin(), v1.end(), greater<int>());
	for_each(v1.begin(), v1.end(), [](int val){cout << val << " "; });
	cout << endl;
}

 

random_shuffle(iterator beg, iterator end) 洗牌

void test03(){
	vector<int>v;
	for (int i = 0; i < 10;i++){
		v.push_back(i);
	}
	random_shuffle(v.begin(), v.end());
	for_each(v.begin(), v.end(), [](int val){cout << val << " "; });
}

他有一个缺陷就是,每次的运行结果都是相同的,因为你可以做一个随机种子

//头文件
#include<ctime>

int main(){
        //随机种子
	srand((unsigned int)time(NULL));	
}

 

reverse(iterator beg, iterator end)

void test04(){
	vector<int>v;
	for (int i = 0; i < 10; i++){
		v.push_back(i);
	}

	reverse(v.begin(), v.end());
	for_each(v.begin(), v.end(), [](int val){cout << val << " "; });
}

 

 

 

常用拷贝和替换算法

/*
	copy算法 将容器内指定范围的元素拷贝到另一容器中
	@param beg 容器开始迭代器
	@param end 容器结束迭代器
	@param dest 目标起始迭代器
*/
copy(iterator beg, iterator end, iterator dest)
/*
	replace算法 将容器内指定范围的旧元素修改为新元素
	@param beg 容器开始迭代器
	@param end 容器结束迭代器
	@param oldvalue 旧元素
	@param oldvalue 新元素
*/
replace(iterator beg, iterator end, oldvalue, newvalue)
/*
	replace_if算法 将容器内指定范围满足条件的元素替换为新元素
	@param beg 容器开始迭代器
	@param end 容器结束迭代器
	@param callback函数回调或者谓词(返回Bool类型的函数对象)
	@param oldvalue 新元素
*/
replace_if(iterator beg, iterator end, _callback, newvalue)
/*
	swap算法 互换两个容器的元素
	@param c1容器1
	@param c2容器2
*/
swap(container c1, container c2)

 

copy算法 将容器内指定范围的元素拷贝到另一容器中

void test01(){
	vector<int>v;
	for (int i = 0; i < 10; i++){
		v.push_back(i);
	}

	vector<int>vTarget;
	vTarget.resize(v.size());

	//下面两种写法的效果是一样的,都是拷贝然后输出
	copy(v.begin(), v.end(), vTarget.begin());
	for_each(vTarget.begin(), vTarget.end(), [](int val) {cout << val << " "; });
	copy(vTarget.begin(), vTarget.end(), ostream_iterator<int>(cout, " "));
}

 

replace算法 将容器内指定范围的旧元素修改为新元素

replace_if算法 将容器内指定范围满足条件的元素替换为新元素

class MyCompare{
public:
	bool operator()(int v){
		return v > 3;
	}
};
void test02(){
	vector<int>v;
	for (int i = 0; i < 10; i++){
		v.push_back(i);
	}

	//需求 把容器中的3  替换成300
	replace(v.begin(), v.end(), 3, 300);

	copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
	cout << endl;

	//需求  把容器中所有大于3的数字 都替换成 30000
	replace_if(v.begin(), v.end(), MyCompare(), 30000);
	copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
}

 

swap算法 互换两个容器的元素

void test03(){
	vector<int>v1;
	for (int i = 0; i < 10; i++){
		v1.push_back(i);
	}

	vector<int>v2;
	v2.push_back(10);
	v2.push_back(30);
	v2.push_back(20);
	v2.push_back(40);

	cout << "交换前数据:" << endl;

	copy(v1.begin(), v1.end(), ostream_iterator<int>(cout, " "));
	cout << endl;
	copy(v2.begin(), v2.end(), ostream_iterator<int>(cout, " "));
	cout << endl;

	cout << "交换后的数据:" << endl;

	swap(v1, v2);

	copy(v1.begin(), v1.end(), ostream_iterator<int>(cout, " "));
	cout << endl;
	copy(v2.begin(), v2.end(), ostream_iterator<int>(cout, " "));
	cout << endl;
}

 

 

 

常用算数生成算法

头文件

#include <numeric>

 

/*
	accumulate算法 计算容器元素累计总和
	@param beg 容器开始迭代器
	@param end 容器结束迭代器
	@param value累加值
*/
accumulate(iterator beg, iterator end, value)
/*
	fill算法 向容器中添加元素
	@param beg 容器开始迭代器
	@param end 容器结束迭代器
	@param value t填充元素
*/
fill(iterator beg, iterator end, value)

 

accumulate算法 计算容器元素累计总和

void test01(){
	vector<int>v;
	for (int i = 0; i <= 100;i++){
		v.push_back(i);
	}

	//0~100累积和  5050
	//第三个参数  起始累加值
	int sum = accumulate(v.begin(), v.end(), 0);
	cout << "总和为:" << sum << endl;
}

 

fill算法 向容器中添加元素

void test02(){
	vector<int>v;
	v.resize(10);//适于前期填充数据
	fill(v.begin(), v.end(), 1000); //适于在原有数据的基础上填充数据
	copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
}

 

 

 

常用集合算法

  • 交集 set_intersection
  • 并集 set_union
  • 差集 set_difference
/*
	set_intersection算法 求两个set集合的交集
	注意:两个集合必须是有序序列
	@param beg1 容器1开始迭代器
	@param end1 容器1结束迭代器
	@param beg2 容器2开始迭代器
	@param end2 容器2结束迭代器
	@param dest  目标容器开始迭代器
	@return 目标容器的最后一个元素的迭代器地址
*/
set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)
/*
	set_union算法 求两个set集合的并集
	注意:两个集合必须是有序序列
	@param beg1 容器1开始迭代器
	@param end1 容器1结束迭代器
	@param beg2 容器2开始迭代器
	@param end2 容器2结束迭代器
	@param dest  目标容器开始迭代器
	@return 目标容器的最后一个元素的迭代器地址
*/
set_union(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)
/*
	set_difference算法 求两个set集合的差集
	注意:两个集合必须是有序序列
	@param beg1 容器1开始迭代器
	@param end1 容器1结束迭代器
	@param beg2 容器2开始迭代器
	@param end2 容器2结束迭代器
	@param dest  目标容器开始迭代器
	@return 目标容器的最后一个元素的迭代器地址
*/
set_difference(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)

 

set_intersection算法 求两个set集合的交集

注意:两个集合必须是有序序列

void test01(){
	vector<int>v1;
	vector<int>v2;

	for (int i = 0; i < 10;i++){
		v1.push_back(i);
		v2.push_back(i + 5);
	}

	vector<int> vTarget;
	vTarget.resize( min(v1.size(),v2.size()));

	vector<int>::iterator itEnd= set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());

	copy(vTarget.begin(), itEnd, ostream_iterator<int>(cout, " "));
}

 

set_union算法 求两个set集合的并集

注意:两个集合必须是有序序列

void test02(){
	vector<int>v1;
	vector<int>v2;

	for (int i = 0; i < 10; i++){
		v1.push_back(i);
		v2.push_back(i + 5);
	}

	vector<int> vTarget;
	vTarget.resize(v1.size()+v2.size());

	vector<int>::iterator itEnd = set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());

	copy(vTarget.begin(), itEnd, ostream_iterator<int>(cout, " "));
}

 

set_difference算法 求两个set集合的差集

注意:两个集合必须是有序序列

void test03(){
	vector<int>v1;
	vector<int>v2;

	for (int i = 0; i < 10; i++){
		v1.push_back(i);
		v2.push_back(i + 5);
	}

	vector<int> vTarget;
	vTarget.resize( max(v1.size(),v2.size() ));

	//v1差v2
	vector<int>::iterator itEnd = set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());

	copy(vTarget.begin(), itEnd, ostream_iterator<int>(cout, " "));
	cout << endl;

	//v2 差 v1
	itEnd = set_difference(v2.begin(), v2.end(), v1.begin(), v1.end(), vTarget.begin());
	copy(vTarget.begin(), itEnd, ostream_iterator<int>(cout, " "));
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值