【C++初阶】比较仿函数/函数对象入门

hello,各位读者大大们你们好呀

系列专栏:【C++学习与应用】

✒️✒️本篇内容:比较仿函数的代码样例,比较仿函数三种不同难度的应用示例

作者简介:计算机海洋的新进船长一枚,请多多指教( •̀֊•́ ) ̖́-

目录

一、代码样例 

二、使用场景(示例)

1.简单应用

2.冒泡排序

3.priority_queue的模拟实现


一、代码样例 

比较仿函数相当于一个类对象,通常使用它的时候要求重载一个运算符 —— 括号运算符【operator()】

因为是比较仿函数,返回默认值,所以我们通常使用bool

bool operator()() 

 为了让仿函数使用更广泛,可将其变为模板

下面代码就实现了 x 和 y 的比较

	template
	class less
	{
    //class默认私有,所以需要加public
	public:
		bool operator()(const T& x, const T& y) const
		{
			return x < y;
		}
	};
	template
	class greater
	{
	public:
		bool operator()(const T& x, const T& y) const
		{
			return x > y;
		}
	};

为了与库区别开来,我们通常会创造一个命名空间存放比较仿函数

#include
using namespace std;

// 仿函数/函数对象
namespace Lin
{
	template
	class less
	{
	public:
		bool operator()(const T& x, const T& y) const
		{
			return x < y;
		}
	};

	template
	class greater
	{
	public:
		bool operator()(const T& x, const T& y) const
		{
			return x > y;
		}
	};
}


二、使用场景(示例)

1.简单应用

仿函数的对象可以像函数一样使用,因此被称为仿函数

int main()
{
    Lin::less lessFunc;
    lessFunc(1, 2);    //等价于下方的运算符重载
    //lessFunc.operator()(1, 2);
}

2.冒泡排序

添加一个额外的模板Compare,在函数中创建一个Compare的对象com,使代码运行时能进行推演。

转化前

template
void BubbleSort(T* a, int n)
{
    ...
    if (a[i] < a[i - 1])
    ...
}

转化后 

template
//void BubbleSort(T* a, int n, const Compare& com) - 没有成员变量的类只有1个字节,拷贝代价不大,因此可以不用&
void BubbleSort(T* a, int n, Compare com)
{
	for (int j = 0; j < n; ++j)
	{
		int exchange = 0;
		for (int i = 1; i < n - j; ++i)
		{
			//if (a[i] < a[i - 1])
			if (com(a[i], a[i - 1]))
			{
				swap(a[i - 1], a[i]);
				exchange = 1;
			}
		}

		if (exchange == 0)
		{
			break;
		}
	}
}

测试用例

int main()
{
	Lin::less lessFunc;
	Lin::greater greaterFunc;

	int a[] = { 2, 3, 4, 5, 6, 1, 2, 4, 9 };

    //升序
	//BubbleSort(a, sizeof(a) / sizeof(int), lessFunc); - lessFunc有名对象
	BubbleSort(a, sizeof(a) / sizeof(int), Lin::less()); //Lin::less()匿名对象
	for (auto e : a)
	{
		cout << e << " ";
	}
	cout << endl;
    
    //降序
	BubbleSort(a, sizeof(a) / sizeof(int), greaterFunc);
	for (auto e : a)
	{
		cout << e << " ";
	}
	cout << endl;

	return 0;
}

3.priority_queue的模拟实现

#include
#include
using namespace std;

namespace Lin
{
	template
	class less
	{
	public:
		bool operator()(const T& x, const T& y) const
		{
			return x < y;
		}
	};

	template
	class greater
	{
	public:
		bool operator()(const T& x, const T& y) const
		{
			return x > y;
		}
	};


	template, class Compare = less>
	class priority_queue
	{
	public:
		priority_queue()
		{}

		template 
		priority_queue(InputIterator first, InputIterator last)
			:_con(first, last)
		{
			// 
			for (int i = (_con.size() - 1 - 1) / 2; i >= 0; --i)
			{
				adjust_down(i);
			}
		}

		void adjust_up(size_t child)
		{
			Compare com;
			size_t parent = (child - 1) / 2;
			while (child > 0)
			{
				//if (_con[parent] < con[child])
				if (com(_con[parent], _con[child]))
				{
					swap(_con[child], _con[parent]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}

		void push(const T& x)
		{
			_con.push_back(x);

			adjust_up(_con.size() - 1);
		}

		void adjust_down(size_t parent)
		{
			Compare com;
			size_t child = parent * 2 + 1;
			while (child < _con.size())
			{
				//if (child+1 < _con.size() && _con[child] < _con[child+1])
				if (child + 1 < _con.size() && com(_con[child], _con[child + 1]))
				{
					child++;
				}

				//if (_con[parent] < _con[child])
				if (com(_con[parent], _con[child]))
				{
					swap(_con[child], _con[parent]);
					parent = child;
					child = parent * 2 + 1;
				}
				else
				{
					break;
				}
			}
		}

		void pop()
		{
			swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();

			adjust_down(0);
		}

		const T& top() const
		{
			return _con[0];
		}

		bool empty() const
		{
			return _con.empty();
		}

		size_t size() const
		{
			return _con.size();
		}
	private:
		Container _con;
	};
}



int main()
{
	//Lin::priority_queue pq; // < // 大堆 - 缺省
	Lin::priority_queue, greater> pq; // >  // 小堆
	pq.push(3);
	pq.push(1);
	pq.push(2);
	pq.push(5);

	while (!pq.empty())
	{
		cout << pq.top() << " ";
		pq.pop();
	}
	cout << endl;

	return 0;
}

【C++初阶】比较仿函数/函数对象入门_第1张图片


事实上,仿函数的不仅仅只有比较仿函数一种,比较仿函数的应用场景也不仅有博主所列出来的那么少,如果大家有兴趣的话,不妨去找更多相关资料继续深入学习,这里博主仅作入门级讲解,希望能抛砖引玉。

比较仿函数的知识大概就讲到这里啦,博主后续会继续更新更多C++的相关知识,干货满满,如果觉得博主写的还不错的话,希望各位小伙伴不要吝啬手中的三连哦!你们的支持是博主坚持创作的动力! 

你可能感兴趣的:(C++学习与应用,c++,开发语言,c语言,算法,数据结构)