【C++】 STL -- 算法(一)

news/2025/2/9 1:30:21 标签: c++, 算法, 开发语言, 函数对象, 谓词, 适配器

【C++】 STL – 算法(一)


文章目录


前言

本篇文章将讲到函数对象谓词,内建函数对象适配器


一、函数对象

本质是一个类的对象,因此称为函数对象,也叫仿函数

class MyPrint
{
public:
	void operator()(int num)
	{
		cout << num << endl;
		m_Count++;
	}

	int m_Count = 0;
};

void myPrint02(int num)
{
	cout << num << endl;
}

void test01()
{
	MyPrint myPrint;
	myPrint(100); //本质是一个类的对象,因此称为函数对象,也叫仿函数

	myPrint02(100);
}

函数对象 超出了普通函数的概念,可以拥有自己状态

void test02()
{
	//函数对象 超出了普通函数的概念,可以拥有自己状态

	MyPrint myPrint;
	myPrint(100);
	myPrint(100);
	myPrint(100);
	myPrint(100);

	cout << "调用次数为: " << myPrint.m_Count << endl;
}

函数对象可以作为函数参数

void doPrint(MyPrint myPrint , int num)
{
	myPrint(num);
}

void test03()
{
	doPrint(MyPrint(), 1000);
}

二、谓词

一元谓词

//一元谓词
class GreaterThan20
{
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);


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


}

二元谓词

//二元谓词
void myPrintInt( int val)
{
	cout << val << " ";
}

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

void test02()
{
	vector<int>v;

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

	sort(v.begin(), v.end()); //从小到大

	for_each(v.begin(), v.end(), myPrintInt);
	cout << endl;


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

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

	cout << endl;
}

三、内建函数对象

引入头文件 #include< functional>
取反 negate
加法 plus
大于 greater

/*
template<class T> T negate<T>//取反仿函数  一元运算
*/

void test01()
{
	negate<int>n;

	cout << n(10) << endl;

}
//template<class T> T plus<T>//加法仿函数
void test02()
{
	plus<int> p;

	cout << p(10, 10) << endl;

}

//template<class T> bool greater<T>//大于
void test03()
{
	vector<int>v;
	v.push_back(20);
	v.push_back(50);
	v.push_back(10);
	v.push_back(30);
	v.push_back(40);

	//从大到小排序
	sort(v.begin(), v.end(), greater<int>());


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

四、适配器

函数对象适配器

class MyPrint :public binary_function<int,int,void>
{
public:
	void operator()(int val , int start)const 
	{
		cout << "val = " << val << " start = " << start <<  " sum = " <<val +  start << endl;
	}
};
//1、函数对象适配器
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 进行绑定
//2、继承 public binary_function<参数1 类型,参数2类型,返回值类型>
//3、加const

取反适配器

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

	//一元取反
	//vector<int>::iterator pos = find_if(v.begin(), v.end(), not1( GreaterThanFive()));

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

	if (pos != v.end())
	{
		cout << "找到小于5的值为: " << *pos << endl;
	}
	else
	{
		cout << "未找到" << endl;
	}


	//二元取反
	sort(v.begin(), v.end(),  not2 (less<int>()));
	for_each(v.begin(), v.end(), [](int val){cout << val << endl; });
}

//1、利用not1进行取反
//2、继承 public unary_function<int,bool>
//3、加const


函数适配器

void myPrint3( int val , int start) 
{
	cout << val + start << endl;
}
//3、 函数适配器
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(myPrint3), 1000));
}

成员函数适配器

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

	void showPerson()
	{
		cout << "成员函数----姓名: " << this->m_Name << " 年龄: " << this->m_Age << endl;
	}

	void addAge()
	{
		this->m_Age += 100;
	}

	string m_Name;
	int m_Age;
};

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

void test04()
{
	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);
	//利用 mem_fun_ref
	for_each(v.begin(), v.end(),  mem_fun_ref(&Person::showPerson));
	for_each(v.begin(), v.end(), mem_fun_ref(&Person::addAge));
	for_each(v.begin(), v.end(), mem_fun_ref(&Person::showPerson));
}


总结

1函数对象
1.1本质是一个类的对象,因此称为函数对象,也叫仿函数
1.2函数对象 超出了普通函数的概念,可以拥有自己状态
1.3函数对象可以作为函数参数
2谓词
2.1普通函数或者仿函数的返回值是bool类型,称为谓词
2.2一元谓词
2.2.1查找容器中大于20的数字 find_if
2.3二元谓词
2.3.1对容器进行排序 sort
2.4lambda表达式 {}
3内建函数对象
3.1引入头文件 #include< functional>
3.2取反 negate
3.3加法 plus
3.4大于 greater
4适配器
4.1函数对象适配器
4.1.1//1、利用bind2nd 进行绑定
4.1.2//2、继承 public binary_function<参数1 类型,参数2类型,返回值类型>
4.1.3//3、加const
4.2取反适配器
4.2.1一元取反 not1
4.2.1.1//1、利用not1进行取反
4.2.1.2//2、继承 public unary_function<int,bool>
4.2.1.3//3、加const
4.2.2二元取反 not2
4.3函数指针适配器
4.3.1ptr_fun将普通函数指针 适配成函数对象
4.4成员函数适配器
4.4.1如果存放的是对象实体 mem_fun_ref
4.4.2如果存放的是对象指针 mem_fun

到这里这篇文章的内容就结束了,谢谢大家的观看,如果有好的建议可以留言喔,谢谢大家啦!


http://www.niftyadmin.cn/n/5845428.html

相关文章

用AVFrame + AVPacket 完成accede编码和直接用ffmpeg命令行实现acc编码的对比

在使用 FFmpeg 进行 AAC 音频编码时,可以选择两种方式:通过编程接口(如 AVFrame 和 AVPacket)实现 AAC 编码,或者直接使用 FFmpeg 命令行工具。这两种方式各有特点,适用于不同的场景。以下是对两种方法的详细分析,包括它们的区别、优缺点以及适用场景。 一、通过 AVFram…

【Android开发AI实战】基于CNN混合YOLOV实现多车牌颜色区分且针对车牌进行矫正识别(含源码)

文章目录 引言单层卷积神经网络&#xff08;Single-layer CNN&#xff09;&#x1f4cc; 单层 CNN 的基本结构&#x1f4cc; 单层 CNN 计算流程图像 透视变换矫正车牌c实现&#x1fa84;关键代码实现&#xff1a;&#x1fa84;crnn结构图 使用jni实现高级Android开发&#x1f3…

安卓7以上抓包证书安装

安卓7以上抓包证书安装 fiddler 用户可以直接试试这个文件 前提是要root过了&#xff0c;如果是模拟器就很容易开启 前提&#xff1a;要有openssl工具&#xff0c;在linux一个指令就可以下载了&#xff1a;sudo apt-get install openssl,windons则是在https://www.openssl.org/…

LM Studio 部署本地大语言模型

一、下载安装 1.搜索&#xff1a;lm studio LM Studio - Discover, download, and run local LLMs 2.下载 3.安装 4.更改成中文 二、下载模型(软件内下载) 1.选择使用代理&#xff0c;否则无法下载 2.更改模型下载目录 默认下载位置 C:\Users\用户名\.lmstudio\models 3.搜…

算法日记13:SC41树状数组(区间修改)

一、题目&#xff1a; 二、题解&#xff1a; 在单点修改中&#xff0c;我们用t[i]来维护原数组2.1:在区间修改中&#xff0c;我们将维护原数组的差分数组 接下来&#xff0c;让我们来回顾一些差分的性质 此时&#xff0c;假设我们需要求 a 1 a 2 a 3 a 4 a1a2a3a4 a1a2a3a…

LeetCode:59. 螺旋矩阵 II(模拟 Java)

目录 59. 螺旋矩阵 II 题目描述&#xff1a; 实现代码与解析&#xff1a; 模拟 原理思路&#xff1a; 59. 螺旋矩阵 II 题目描述&#xff1a; 给你一个正整数 n &#xff0c;生成一个包含 1 到 n2 所有元素&#xff0c;且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 ma…

s1:简单测试-时间规模化

25年1月来自斯坦福、西雅图 UW、AI2 和 Contextual AI 的论文“s1: Simple test-time scaling”。 测试-时间规模化是一种很有前途的语言建模新方法&#xff0c;它使用额外的测试-时间计算来提高性能。最近&#xff0c;OpenAI 的 o1 模型展示这种能力&#xff0c;但并未公开分…

apisix的real-ip插件使用说明

k8s集群入口一般都需要过负载均衡&#xff0c;然后再到apisix。 这时候如果后台业务需要获取客户端ip&#xff0c;可能拿到的是lb或者网关的内网ip。 这里一般要获取真实ip需要做几个处理。 1. 负载均衡上&#xff0c;一般支持配置获取真实ip参数&#xff0c;需要配置上。然…