C++系列-谓词predicate

谓词predicate


赵师秀 宋《约客》

黄梅时节家家雨,青草池塘处处蛙。

有约不来过夜半,闲敲棋子落灯花


💢什么是谓词

  • 🥝谓词是一个可以调用的对象
  • 🥝它接收一个或一个或多个参数,并返回一个或布尔值
  • 🥝谓词通常用于算法中 ,以指定特定的条件,例如在排序算法中,可以用谓词指定排序的规则,在查找算法中,可以使用谓词来确定是否找到了满足特定条件的元素。

💢💢函数(function)谓词

  • 🍋函数的定义满足谓词的定义条件。
  • 🍋在使用时通过传递函数名实现 。

👉👉👉

先看find_if函数的定义,返回_First,是一个迭代器对象。

_Pred(_UFirst),_Pred是执行实参中传入的参数,在本类中,是一个函数名,函数名()是函数的调用。 _UFirst是迭代器指向的内容。

在for循环中,循环从_First到_Last迭代器指向的每一个元素,将其作为函数的参数,执行函数操作,当出现返回true的时候,退出循环,即找到第一个满足条件的元素就退出。

vector::iterator it = find_if(vec1.begin(), vec1.end(), is_even)中的is_even要传递函数名称。是一个谓词。

cpp 复制代码
_EXPORT_STD template <class _InIt, class _Pr>
_NODISCARD _CONSTEXPR20 _InIt find_if(_InIt _First, const _InIt _Last, _Pr _Pred) 
{ // find first satisfying _Pred
    _Adl_verify_range(_First, _Last);
    auto _UFirst      = _Get_unwrapped(_First);
    const auto _ULast = _Get_unwrapped(_Last);
    for (; _UFirst != _ULast; ++_UFirst) {
        if (_Pred(*_UFirst)) {
            break;
        }
    }

    _Seek_wrapped(_First, _UFirst);
    return _First;
}
cpp 复制代码
code:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

bool is_even(int &val)
{
	return val % 2 == 0;
}

void test01()
{
	vector<int> vec1{1, 2, 3, 4, 5, 6};
	// find_if(_InIt _First, const _InIt _Last, _Pr _Pred) { // find first satisfying _Pred
	vector<int>::iterator it = find_if(vec1.begin(), vec1.end(), is_even);
	if(it == vec1.end())
	{
		cout << "没有找到" << endl;
	}
	else
	{
		cout << "第一个偶数是: " << *it << endl;
	}
}

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

result:
第一个偶数是: 2

💢💢函数指针(function pointer)谓词

  • 🍓使用函数指针做谓词,与上述函数做谓词基本一致,只是使用函数指针中转了一次。
  • 🍓在使用时通过传递函数指针实现 。
cpp 复制代码
code:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

bool greater_than10(int &val)
{
	return val > 10;
}

void test01()
{
	vector<int> vec1{1, 2, 13, 24, 5, 6};
	bool (*p_greater_than10)(int&); // 定义函数指针
	p_greater_than10 = greater_than10;
	vector<int>::iterator it = find_if(vec1.begin(), vec1.end(), greater_than10); // 函数指针作为谓词
	if(it == vec1.end())
	{
		cout << "没有找到" << endl;
	}
	else
	{
		cout << "第一个大于10的数是: " << *it << endl;
	}
}

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

result:
第一个大于10的数是: 13

💢💢函数对象(Function Object)谓词

  • 🍈 函数对象中重载函数的调用(), 使其可以被调用, 作为谓词。
  • 🍈 函数对象使用的本质就是对()进行运算符重载,并且返回类型为bool型,满足谓词的条件。

👉👉👉

在find_if函数中,执行 _Pred(_UFirst),_Pred是执行实参中传入的参数,在本类中,即函数对象,函数对象( _UFirst)即调用重载的()成员函数,实现了重载()函数中执行的语句。

Greater(1),创建匿名函数对象,其中的参数传入,使得在调用()时,有了明确的比较对象。

cpp 复制代码
code:
#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;
class Greater
{
public:
	Greater(int val) :m_base(val) {}
	bool operator()(int val)
	{
		return val > m_base;
	}
private:
	int m_base;
};

int main()
{
	vector<int>vec1 = { 0,-1,1,2,4,9,5,54,45,56 };
	// 函数对象做谓词,并且使用有参构造传入参数作为谓词判断的条件
	vector<int>::iterator iter = find_if(vec1.begin(), vec1.end(), Greater(1));
	cout << *iter << endl;
	system("pause");
	return 0;
}

result:
2

💢💢lambda表达式谓词

👉👉👉

[](int val)->bool{return val > 3;} lambda表达式作参数,这是一个匿名函数,在find_if 的_Pred(*_UFirst)中的_Pred就指向了该匿名函数。

cpp 复制代码
code:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;


int main()
{
	vector<int>vec1 = { 0,-1,1,2,4,9,5,54,45,56 };
	// lambda做谓词
	vector<int>::iterator iter = find_if(vec1.begin(), vec1.end(), [](int val)->bool{return val > 3;});
	cout << *iter << endl;
	system("pause");
	return 0;
}

result:
4

库定义的函数对象(Library-Defined Function Object)谓词

💢💢库定义的函数对象谓词

  • 🍉 标准库中已经定义好一些用于特定条件判断的函数对象。
  • 🍉 比如less是用于比较两个对象的大小的函数对象谓词。

💢谓词的应用

  • 🍐谓词通常用于算法中,指定特定的条件。
  • 🍐 例如在排序算法中,可以使用谓词来定义排序的规则。在查找算法中,可以使用谓词来确定是否找到了满足特定条件的元素。

💢一元和二元谓词

  • 🥝一元谓词接受一个参数。
  • 🥝二元谓词接受两个个参数。

一元和二元谓词举例

cpp 复制代码
code:
#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;
class Greater
{
public:
	Greater(int val) :m_base(val) {} // 重载的(), 函数可以接受一个参数,故Greater的对象是二元谓词
	bool operator()(int val)
	{
		return val > m_base;
	}
private:
	int m_base;
};

template<class T>
class MyCompare
{
public:
	bool operator()(T val1, T val2) // 重载的(), 函数可以接受两个参数,故MyCompare的对象是二元谓词
	{
		return val1 > val2;
	}
};

void print_vector(vector<int> &vec)
{
	for (auto i_vec : vec)
	{
		cout << i_vec << " ";
	}
	cout << endl;
}

int main()
{
	vector<int>vec1 = { 0,-1,1,2,4,9,5,54,45,56 };
	cout << "排序前:" << endl;
	print_vector(vec1);
	// sort默认是升序排列,传递函数对象作为参数,改为降序排列
	sort(vec1.begin(), vec1.end(), MyCompare<int>());
	cout << "排序后:" << endl;
	print_vector(vec1);
	vector<int>::iterator iter = find_if(vec1.begin(), vec1.end(), Greater(1));
	cout << *iter << endl;

	system("pause");
	return 0;
}

result:
排序前:
0 -1 1 2 4 9 5 54 45 56
排序后:
56 54 45 9 5 4 2 1 0 -1
56
相关推荐
常某某的好奇心14 分钟前
56 - I. 数组中数字出现的次数
算法
WZF-Sang16 分钟前
Linux权限理解【Shell的理解】【linux权限的概念、管理、切换】【粘滞位理解】
linux·运维·服务器·开发语言·学习
_Power_Y19 分钟前
JavaSE:11、内部类
java·开发语言
hungry123419 分钟前
CF EDU 169
算法
你可以自己看1 小时前
python的基础语法
开发语言·python
爱编程的小新☆1 小时前
C语言内存函数
c语言·开发语言·学习
程序猿阿伟1 小时前
《C++移动语义:解锁复杂数据结构的高效之道》
数据结构·c++·html
尘浮生1 小时前
Java项目实战II基于Spring Boot的宠物商城网站设计与实现
java·开发语言·spring boot·后端·spring·maven·intellij-idea
勤奋的小王同学~2 小时前
怎么修改mvn的java版本
java·开发语言
夜清寒风2 小时前
opencv学习:图像掩码处理和直方图分析及完整代码
人工智能·opencv·学习·算法·机器学习·计算机视觉