C++中函数对象、内建函数以及STL常用的标准算法

谓词

先理解一下什么是谓词
仿函数的返回值类型是bool数据类型,称为谓词,
其中仿函数的形参有一个就是一元谓词,两个就是二元谓词

代码演示:

class GreaterFive
{
public:
	bool operator()(int val) // 形参有一个就是一元谓词,两个就是二元
	{
		return val > 5;
	}
};
void demo01()
{
	vector<int> v;
	for (int i = 0; i < 10; ++i) {
		v.push_back(i);
	}
	// GreaterFive() 匿名函数对象
	vector<int>::iterator it = find_if(v.begin(), v.end(), GreaterFive());
	if (it == v.end()) {
		cout << "没有大于5的数" << endl;
	}
	else {
		cout << *it << endl;
	}
}

class MySort
{
public:
	// 重写()的返回值是bool类型称为谓词
	bool operator()(int a, int b) // 二元谓词
	{
		return a > b;
	}
};
void demo02()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(3);
	v.push_back(5);
	v.push_back(2);
	v.push_back(4);
	sort(v.begin(), v.end(), MySort()); // 降序
}

函数对象

函数对象就是仿函数
1、函数对象在使用时可以有参数也可以有返回值
2、函数对象超出普通对象的概念,函数对象可以有自己的状态
3、函数对象可以做参数传递

代码演示:

// 1、函数对象在使用时可以有参数也可以有返回值
class MyAdd
{
public:
	int operator()(int a, int b)
	{
		return a + b;
	}

};
// 2、函数对象超出普通对象的概念,函数对象可以有自己的状态
class MyPrint
{
public:
	MyPrint()
	{
		this->count = 0;
	}
	void operator()(string test)
	{
		cout << test << endl;
		this->count++; // 可以通过count来记录仿函数被调用的次数
	}
	int count;
};
void demo01()
{
	MyAdd ma;
	cout << ma(10, 11) << endl; // 函数对象
	
}
void demo02()
{
	MyPrint mp;
	mp("123");
	mp("123");
	mp("123");
	mp("123");
	cout << "调用了" << mp.count << "次" << endl; // 函数对象自己的状态
}
// 3、函数对象可以做参数传递
void demo03(MyPrint& sp)
{
	sp("123");
}
void test()
{
	MyPrint mp;
	demo03(mp);
}

内建函数

内建仿函数(STL已经写好的仿函数,需要引入#include<functional>头文件
代码演示:算数仿函数
1、negate 一元仿函数 取反仿函数
2、plus 二元反函数 算数仿函数

使用内建函数需要引入<functional>头文件

void demo01()
{
	negate<int> n; // 创建函数对象
	cout << n(50) << endl; // 对50取反 为-50
}

void demo02()
{
	plus<int> p; 
	cout << p(10, 20) << endl; // 二元仿函数,相加
}

关系仿函数
1、greater 大于仿函数
2、equal_to 等于仿函数
3、not_equal_to 不等于仿函数
4、greater_equal 大于等于仿函数
5、less 小于仿函数
6、less_equal 小于等于仿函数

void demo03()
{
	vector<int> v;
	v.push_back(10);
	v.push_back(20);
	v.push_back(50);
	v.push_back(30);
	v.push_back(40);
	sort(v.begin(), v.end(), greater<int>()); // 降序
	// 其他关系仿函数用途类似,都是当作谓词处理
}

代码演示:逻辑仿函数
1、logical_and 与
2、logical_or 或
3、logical_not 非

void demo04()
{
	vector<bool>v;
	v.push_back(true);
	v.push_back(false);
	v.push_back(true);

	// 利用取反仿函数 搬运到另一个容器在搬运期间取反
	vector<bool> v2;
	v2.resize(v.size()); // 使用transform搬运前必须使其空间足够
	transform(v.begin(), v.end(), v2.begin(), logical_not<bool>());
}

STL常用标准算法

STL的标准算法都需要引入<algorithm>头文件
还有<numeric> // 小型的算法库,只包含几个序列上进行简单数学运算的算法

1、遍历算法
1、for_each : 遍历
2、transform :搬运

void print01(int val)
{
	cout << val << " ";
}
class print02
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};
void demo01()
{
	vector<int> v;
	v.push_back(10);
	v.push_back(40);
	v.push_back(30);
	v.push_back(20);

	for_each(v.begin(), v.end(), print01); // 调用全局函数作为遍历操作
	cout << endl;
	for_each(v.begin(), v.end(), print02()); // 调用仿函数作为遍历操作
}
int trans01(int val)
{
	return val; // 不操作直接返回
}
class trans02
{
public:
	int operator()(int val) {
		return val;
	}
};
// 搬运
void demo02()
{
	vector<int> v;
	v.push_back(10);
	v.push_back(40);
	v.push_back(30);
	v.push_back(20);

	vector<int> v2;
	v2.resize(v.size()); // 搬运目标容器必须有足够的空间
	transform(v.begin(), v.end(), v2.begin(), trans01); // 调用全局函数作为搬运时操作
	transform(v.begin(), v.end(), v2.begin(), trans02()); // 调用仿函数作为搬运时操作
}

2、查找算法
1、find:按值查找
2、find_if:条件查找
3、adjacent_find:查找相邻元素一样的情况
4、binary_search:按值二分查找

class Myif
{
public:
	bool operator()(int val) {
		return val > 20;
	}
};
void demo03()
{
	vector<int> v;
	v.push_back(10);
	v.push_back(20);
	v.push_back(30);
	v.push_back(30);
	v.push_back(40);

	vector<int>::iterator it = find(v.begin(), v.end(), 10); // 按值查找
	// 按谓词条件范围查找,返回第一个符合条件的迭代器
	it = find_if(v.begin(), v.end(), Myif()); 
	
	it = adjacent_find(v.begin(), v.end()); // 查找相邻一样的元素,返回第一个元素的迭代器
	
	// 二分查找指定元素,查到返回true,否则返回false,容器内必须有序
	bool exists = binary_search(v.begin(), v.end(), 20);
}

3、统计算法
1、count:统计指定元素个数
2、count_if:按条件统计元素个数

class Myif
{
public:
	bool operator()(int val) {
		return val > 20;
	}
};
void demo04()
{
	vector<int> v;
	v.push_back(10);
	v.push_back(20);
	v.push_back(30);
	v.push_back(30);
	v.push_back(40);

	int sum = count(v.begin(), v.end(), 30); // 统计指定元素个数

	sum = count_if(v.begin(), v.end(), Myif()); // 按范围统计
}

4、排序算法
1、sort:有序排序
2、random_shuffle:洗牌
3、merge:合并两个有序的容器,将结果输出到新的容器依然有序
4、reverse:逆序

class MySort
{
public:
	bool operator()(int a, int b) {
		return a > b;
	}
};
void demo05()
{
	vector<int> v;
	v.push_back(10);
	v.push_back(20);
	v.push_back(30);
	v.push_back(30);
	v.push_back(40);

	sort(v.begin(), v.end(), MySort()); // 第三参数不传默认升序

	// 随机打乱  洗牌算法
	srand((unsigned int)time(NULL)); // 生成随机种子,使得每次随机值都不一样
	random_shuffle(v.begin(), v.end()); // 随机打乱容器中的元素顺序,用于洗牌

	// 将两个有序序列合并到另一个容器中,整体依然有序
	vector<int> v1;
	v1.push_back(10);
	v1.push_back(20);
	v1.push_back(30);
	v1.push_back(30);
	v1.push_back(40);
	vector<int> v2;
	v2.push_back(10);
	v2.push_back(20);
	v2.push_back(30);
	v2.push_back(30);
	v2.push_back(40);
	vector<int> v3;
	v3.reserve(v1.size() + v2.size()); // 必须有足够的空间
	merge(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());


	// 将容器中的元素逆序
	reverse(v3.begin(), v3.end()); // 将指定区间逆序
}

5、常用拷贝和替换
1、copy:将指定区间内容拷贝到指定容器中
2、copy_if:指定区间按谓词条件拷贝到目标容器中
3、replace:按值替换
4、replace_if:按谓词条件替换

void demo06()
{
	vector<int> v1;
	v1.push_back(10);
	v1.push_back(20);
	v1.push_back(30);
	v1.push_back(30);
	v1.push_back(40);
	vector<int> v2;
	v2.push_back(10);
	v2.push_back(20);
	v2.push_back(30);
	v2.push_back(30);
	v2.push_back(40);

	vector<int> v3;
	v3.reserve(v1.size());
	copy(v1.begin(), v1.end(), v3.begin());// 将指定区间内容拷贝到指定容器中
	// 指定区间按谓词条件拷贝到目标容器中
	copy_if(v1.begin(), v1.end(), v3.begin(), Myif());

	// 替换
	replace(v2.begin(), v2.end(), 20, 100); // 将指定区间的所有20换成100

	// 将指定区间的元素按谓词条件全部替换成指定值
	replace_if(v2.begin(), v2.end(), Myif(), 200); 
}

6、互换

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

	v1.swap(v2); // 容器自带的

	swap(v1, v2); // 标准算法将两容器互换
	// 两种方式效果一样
}

7、算数生成算法 在头文件<numeric>中
1、accumulate:按初始值累加
2、fill:后期重新填充

void demo08()
{
	vector<int> v1;
	for (int i = 1; i < 101; ++i) {
		v1.push_back(i);
	}

	// 第三个参数为累加的初始值,返回指定区间元素累加并加初始值的总和
	int total = accumulate(v1.begin(), v1.end(), 0);// 从0开始累加容器中所有元素
	cout << total << endl; // 打印5050

	total = accumulate(v1.begin(), v1.end(), 2);
	cout << total << endl; // 打印5052
}
void demo09()
{
	vector<int> v1;
	v1.resize(10);

	// 后期重新填充
	fill(v1.begin(), v1.end(), 100); // 将指定区间填充为指定值
}

8、集合算法
1、set_intersection:求交集
2、set_union:求并集
3、set_difference:求差集

void myPrint(int val)
{
	cout << val << " ";
}
// 集合算法
void demo10()
{
	vector<int> v1;
	v1.push_back(10);
	v1.push_back(20);
	v1.push_back(30);
	vector<int> v2;
	v2.push_back(20);
	v1.push_back(30);
	v1.push_back(40);
	vector<int> v3;
	v3.resize(v1.size()+v2.size()); // 目标容器空间必须足够大

	// 求交集, 返回目标容器交集最后一个元素的迭代器
	vector<int>::iterator itEnd = set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());
	for_each(v3.begin(), itEnd, myPrint);// 这里用itEnd,如果用v3.end()会打印多余的数据

	v3.clear();
	// 求并集,返回目标容器并集最后一个元素的迭代器
	itEnd = set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());
	for_each(v3.begin(), itEnd, myPrint);

	v3.clear();
	// 求差集,返回目标容器差集最后一个元素的迭代器
	// v2-v1=v1中不是交集的部分,v1-v2=v2中不是交集的部分
	itEnd = set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());
	for_each(v3.begin(), itEnd, myPrint);

	// 注意:被求集合必须有序
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值