C++学习日记 STL函数对象、谓词、内建函数对象、常见算法集合

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

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

例如:
class Person{
public:
    void operator()()
    {

    }
};

Person p;   //p就是函数对象
p();        //对象使用()时,非常像函数调用  -> 仿函数

二、函数对象的使用。
1、函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值。
2、函数对象超过普通函数的概念,函数对象可以有自己的状态。
3、函数对象可以作为参数传递。

#include 
using namespace std;

/*
1、函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值。
2、函数对象超过普通函数的概念,函数对象可以有自己的状态。
3、函数对象可以作为参数传递。
*/

//1. 函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值。
class MyAdd{
public:
	//类中重载了(),那么这个类的对象,就是函数对象。
	int operator()(int v1,int v2)
	{
		return v1 + v2;
	}
};

void test01()
{
	MyAdd myadd;  //myadd就是一个函数对象
	int ret = myadd(10,20);
	cout << "ret = " << ret << endl; //30
}

//2. 函数对象超过普通函数的概念,函数对象可以有自己的状态。
class Myprint{
public:
	Myprint()
	{
		this->count = 0;
	}

	void operator()(string text)
	{
		cout << text << endl;
		this->count++;
	}

	int count; 
};

void test02()
{
	Myprint myprint;
	myprint("helloworld");
	myprint("helloworld");
	myprint("helloworld");
	myprint("helloworld");
	myprint("helloworld");
	myprint("helloworld");
	myprint("helloworld");
	myprint("helloworld");

	cout << "myprint调用的次数是:" << myprint.count << endl;
}

//3. 函数对象可以作为参数传递。
void doPrint(Myprint &mp,string text)
{
	mp(text);
}

void test03()
{
	Myprint myprint;
	doPrint(myprint,"hello C++");
}

int main()
{
	//test01();
	//test02();
	test03();
	return 0;
}

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

#include 
using namespace std;
#include 
#include 

//一元谓词。
class GreaterFive{
public:
	bool operator()(int val)
	{
		return val > 5;
	}
};

int main()
{
	vector v;
	int i;
	for(i=0;i<10;i++)
	{
		v.push_back(i);  //0~9
	}

	//查找一下容器中有没有大于5的数字。
	//GreaterFive greaterFive;
	//vector::iterator it = find_if(v.begin(),v.end(),greaterFive);  //填有名函数对象  
	
	vector::iterator it = find_if(v.begin(),v.end(),GreaterFive());  //填匿名函数对象
	if(it == v.end())
	{
		cout << "未找到" << endl;
	}
	else{
		cout << "找到了大于5的数字:" << *it << endl;
	}

	return 0;
}

2、二元谓词。

#include 
using namespace std;
#include 
#include 

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

int main()
{
	vector v;
	v.push_back(10);
	v.push_back(40);
	v.push_back(20);
	v.push_back(30);
	v.push_back(50);

	sort(v.begin(),v.end());  //默认是升序的。
	for(vector::iterator it = v.begin();it!=v.end();it++)
	{
		cout << *it << "  ";
	}
	cout << endl;

	//使用函数对象,改变算法策略,使得排序规则从大到小。
	//Mycompare mycompare;
	//sort(v.begin(),v.end(),mycompare);
	sort(v.begin(),v.end(),Mycompare());
	for(vector::iterator it = v.begin();it!=v.end();it++)
	{
		cout << *it << "  ";
	}
	cout << endl;

	return 0;
}

   练习: 使用sort算法来对Person自定义类型进行排序。
          Person 姓名和年龄

#include 
using namespace std;
#include 
#include 

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

	string m_Name;
	int m_Age;
};

class Comparetest{
public:
	bool operator()(Person &p1,Person &p2)
	{
		return p1.m_Age > p2.m_Age;
	}
};

int main()
{
	vector v;

	Person p1("刘备",40);
	Person p2("关羽",50);
	Person p3("张飞",35);
	Person p4("赵云",20);
	Person p5("曹操",38);

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

	cout << "排序前:" << endl;
	for(vector::iterator it = v.begin();it!=v.end();it++)
	{
		cout << "姓名:" << it->m_Name << " 年龄:" << it->m_Age << endl;
	}

	//Comparetest c;
	//sort(v.begin(),v.end(),c);
	sort(v.begin(),v.end(),Comparetest());

	cout << "排序后:" << endl;
	for(vector::iterator it = v.begin();it!=v.end();it++)
	{
		cout << "姓名:" << it->m_Name << " 年龄:" << it->m_Age << endl;
	}

	return 0;
}

四、内建函数对象。
1、意义:
STL中已经内建一些函数对象。

2、分类。
算术仿函数。
关系仿函数。
逻辑仿函数。

3、用法。
这些仿函数所产生的对象,用法与一般函数完全相同。
使用内建函数对象,需要引入头文件:#include

五、算术仿函数。
template T plus       //加法仿函数
template T minus      //减法仿函数
template T multiplies //乘法仿函数
template T divides    //除法仿函数
template T modulus    //取模仿函数
template T negate     //取反仿函数
其中:negate是一元运算,其他都是二元运算。

#include 
using namespace std;

int main()
{
	plus p;
	cout << p(10,20) << endl;

	negate n;  n就是一个函数对象
	cout << n(50) << endl;	

	return 0;
}

六、关系仿函数。
template bool equal_to       //等于
template bool not_equal_to   //不等于
template bool greater        //大于
template bool greater_equal  //大于等于
template bool less           //小于
template bool less_equal     //小于等于

#include 
using namespace std;
#include 
#include 

/*
class Mycompare{
public:
	bool operator()(int v1,int v2)
	{
		return v1 > v2;
	}
};
*/

int main()
{
	vector v;
	v.push_back(10);
	v.push_back(50);
	v.push_back(30);
	v.push_back(40);
	v.push_back(20);

	cout << "排序前:" << endl;
	for(vector::iterator it = v.begin() ;it != v.end() ;it++)
	{
		cout << *it << "  ";
	}
	cout << endl;

	//sort(v.begin(),v.end());              //默认是升序的。
	//sort(v.begin(),v.end(),Mycompare());  //自己写规则,按照降序来排序。
	//sort(v.begin(),v.end(),greater()); //使用内建函数对象


	cout << "排序后:" << endl;
	for(vector::iterator it = v.begin() ;it != v.end() ;it++)
	{
		cout << *it << "  ";
	}
	cout << endl;

	return 0;
}

七、逻辑仿函数。
template bool logical_and    //逻辑与
template bool logical_or     //逻辑或
template bool logical_not    //逻辑非

#include 
using namespace std;
#include 
#include 

//逻辑仿函数

int main()
{
	vector v;
	v.push_back(true);  //1
	v.push_back(false); //0
	v.push_back(true);  //1
	v.push_back(false); //0

	cout << "搬运前:" << endl;
	for(vector::iterator it = v.begin() ;it!=v.end() ;it++)
	{
		cout << *it << " ";  //1 0 1 0
	}
	cout << endl;

	vector v2;
	v2.resize(v.size());

	logical_not ln;
	transform(v.begin(),v.end(),v2.begin(),ln);

	cout <<  "搬运后:" << endl;
	for(vector::iterator it = v2.begin() ; it!=v2.end() ; it++)
	{
		cout << *it << " ";
	}
	cout << endl;

	return 0;
}

八、常见遍历算法。
算法简介:
for_each   //遍历容器
transform  //搬运容器到另一个容器中

#include 
using namespace std;
#include 
#include 

//常见遍历算法。
//for_each   //遍历容器
//transform  //搬运容器到另一个容器中

class Print01{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

void Print02(int val)
{
	cout << val << " ";
}

class Test{
public:
	int operator()(int v)
	{
		return v + 100;
	}
};

int myTest(int v)
{
	return v + 100;
}

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

	//第一种方式: 使用有名函数对象
	//Print01 p1;
	//for_each(v.begin(),v.end(),p1);
	
	//第二种方式: 使用匿名函数对象
	//for_each(v.begin(),v.end(),Print01());
	
	//第三种方式:使用函数
	for_each(v.begin(),v.end(),Print02);
	cout << endl;

	cout << "--------------------------" << endl;

	vector vTarget;  //目标
	vTarget.resize(v.size());

	//transform(v.begin(),v.end(),vTarget.begin(),Test());
	
	transform(v.begin(),v.end(),vTarget.begin(),myTest);
	for_each(vTarget.begin(),vTarget.end(),Print02);
	cout << endl;

	return 0;
}

九、常见查找算法。
find             //查找元素
find_if          //按条件查找元素

#include 
using namespace std;
#include 
#include 

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

	bool operator==(const Person &p)
	{
		if(this->m_Name == p.m_Name && this->m_Age == p.m_Age)
		{
			return true;
		}
		else{
			return false;
		}
	}

	string m_Name;
	int m_Age;
};

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

bool Greater20func(Person &p)
{
	return p.m_Age > 20;
}

int main()
{	
	/*
	vector v;
	int i;
	for(i=0;i<10;i++)
	{
		v.push_back(i);
	}

	//查找一下有没有5这个元素。
	vector::iterator it = find(v.begin(),v.end(),5);
	if(it == v.end())
	{
		cout << "未找到" << endl;
	}
	else{
		cout << "找到了:" << *it << endl;	
	}
	*/

	vector v;

	Person p1("aaa",10);
	Person p2("bbb",20);
	Person p3("ccc",30);
	Person p4("ddd",40);
	Person p5("eee",50);

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

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

	//vector::iterator it = find_if(v.begin(),v.end(),Greater20());
	vector::iterator it = find_if(v.begin(),v.end(),Greater20func);
	if(it == v.end())
	{
		cout << "未找到" << endl;
	}
	else{
		cout << "找到了:" << "姓名:"<< it->m_Name << "年龄:" << it->m_Age << endl; 
	}

	return 0;
}

十、常见查找算法。

#include 
using namespace std;
#include 
#include 

int main()
{
	/*
	vector v;

	v.push_back(0);
	v.push_back(2);
	v.push_back(0);
	v.push_back(3);
	v.push_back(3);
	v.push_back(1);
	v.push_back(3);
	v.push_back(4);
	v.push_back(9);
	v.push_back(9);
	v.push_back(10);
	v.push_back(7);

	vector::iterator it = adjacent_find(v.begin(),v.end());
	if(it == v.end())
	{
		cout << "未找到相邻的元素" << endl;
	}
	else{
		cout << "找到相邻的元素:" << *it < v;
	int i;
	for(i=0;i<10;i++)
	{
		v.push_back(i);
	}
	v.push_back(2);

	bool ret = binary_search(v.begin(),v.end(),9);
	if(ret)
	{
		cout << "找到了元素" << endl;
	}
	else{
		cout << "没有找到元素" << endl;
	}
	return 0;
}

十一、常见查找算法。

#include 
using namespace std;
#include 
#include 

class Greater20{
public:
	bool operator()(int val) // Person&p
	{
		return val > 20;  //return p.m_Age > 20
	}
};

int main()
{
	vector v;
	v.push_back(10);
	v.push_back(30);
	v.push_back(20);
	v.push_back(30);
	v.push_back(30);
	v.push_back(40);

	//统计30出现的次数。
	int num = count(v.begin(),v.end(),30);
	cout << "num = " << num << endl;

	//统计大于20有多少个。
	num = count_if(v.begin(),v.end(),Greater20());
	cout << "num = " << num << endl;
	return 0;
}

十二、常见排序算法。

#include 
using namespace std;
#include 
#include 

class myprint{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

int main()
{
	/*
	srand(time(NULL));

	vector v;

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

	cout << "洗牌前:" << endl;
	for_each(v.begin(),v.end(),myprint());
	cout << endl;

	random_shuffle(v.begin(),v.end());  //内部实现利用rand()来实现的。

	cout << "洗牌前:" << endl;
	for_each(v.begin(),v.end(),myprint());
	cout << endl;
	*/

	vector v1;
	vector v2;

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

	vector vTarget;
	vTarget.resize(v1.size()+v2.size());

	merge(v1.begin(),v1.end(),v2.begin(),v2.end(),vTarget.begin());
	for_each( vTarget.begin() , vTarget.end() , myprint());
	cout << endl;

	cout << "反转前:" << endl;
	for_each(v1.begin(),v1.end(),myprint());
	cout << endl;

	reverse(v1.begin(),v1.end());
	cout << "反转后:" << endl;
	for_each(v1.begin(),v1.end(),myprint());
	cout << endl;

	return 0;
}

十三、常见拷贝和替换算法。

#include 
using namespace std;
#include 
#include 

class myprint{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

class Greater30{
public:
	bool operator()(int val)
	{
		return val >= 30;
	}
};

int main()
{
	vector v1;
	v1.push_back(10);
	v1.push_back(50);
	v1.push_back(30);
	v1.push_back(60);
	v1.push_back(30);
	v1.push_back(40);
	v1.push_back(20);
	v1.push_back(10);
	v1.push_back(30);

	vector v2;
	v2.resize(v1.size());

	copy(v1.begin(),v1.end(),v2.begin());
	for_each(v2.begin(),v2.end(),myprint());
	cout << endl;

	cout << "替换前:" << endl;
	for_each(v1.begin(),v1.end(),myprint());
	cout << endl;

	//replace(v1.begin(),v1.end(),30,70);
	replace_if(v1.begin(),v1.end(),Greater30(),100);

	cout << "替换后:" << endl;
	for_each(v1.begin(),v1.end(),myprint());
	cout << endl;


	cout << "互换前:" << endl;
	for_each(v1.begin(),v1.end(),myprint());
	cout << endl;
	for_each(v2.begin(),v2.end(),myprint());
	cout << endl;

	swap(v1,v2);

	cout << "互换后:" << endl;
	for_each(v1.begin(),v1.end(),myprint());
	cout << endl;
	for_each(v2.begin(),v2.end(),myprint());
	cout << endl;

	return 0;
}

十四、常见算术生成算法。
需要包含头文件:#include

#include 
using namespace std;
#include 
#include 
#include 

class myprint{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

int main()
{
	/*
	vector v;
	int i;
	for(i=0;i<100;i++)
	{
		v.push_back(i);
	}

	int sum = accumulate(v.begin(),v.end(),0);
	cout << sum << endl;
	*/

	vector v;
	v.resize(10);

	fill(v.begin(),v.end(),100);
	for_each(v.begin(),v.end(),myprint());
	cout << endl;
	return 0;
}

十五、常见集合算法。

#include 
using namespace std;
#include 
#include 

class myprint{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};

int main()
{
	vector v1;
	vector v2;

	int i;
	for(i=0;i<10;i++)
	{
		v1.push_back(i);    // 0 1 2 3 4 5 6 7 8 9
		v2.push_back(i+5);  //           5 6 7 8 9 10 11 12 13 14
	}

	//求交集。
	//vector vTarget;  //存放交集结果
	//vTarget.resize(min(v1.size(),v2.size()));

	//返回值:是交集中最后一个元素的迭代器。
	//vector::iterator itEnd = set_intersection(v1.begin(),v1.end(),v2.begin(),v2.end(),vTarget.begin());
	//for_each(vTarget.begin(),itEnd,myprint());
	//cout << endl;
	
	//求并集。
	//vector vTarget;
	//vTarget.resize(v1.size() + v2.size());
	//vector::iterator itEnd = set_union(v1.begin(),v1.end(),v2.begin(),v2.end(),vTarget.begin());
	//for_each(vTarget.begin(),itEnd,myprint());
	//cout << endl;
	
	//求v1与v2的差集。
	vector vTarget;
	vTarget.resize(max(v1.size(),v2.size()));

	//vector::iterator itEnd = set_difference(v1.begin(),v1.end(),v2.begin(),v2.end(),vTarget.begin());
	vector::iterator itEnd = set_difference(v2.begin(),v2.end(),v1.begin(),v1.end(),vTarget.begin());
	for_each(vTarget.begin(),itEnd,myprint());
	cout << endl;
	return 0;
}

你可能感兴趣的:(c++,C++,c++)