C++:仿函数模拟实现STL-priority_queue

本文介绍了如何使用C++中的仿函数实现优先级队列,通过模板参数控制大堆和小堆的逻辑,简化了代码并提高灵活性。重点讲解了文档理解、仿函数的定义、语法以及如何在push和pop操作中使用仿函数进行比较和调整堆结构。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.文档了解

在这里插入图片描述

从priority_queue的文档中,我们可以得出以下几点:

1.priority_queue是一个容器适配器
2.priority_queue它实质是一个堆,且默认为大堆
3.对于参数传入的Compare,从字面意思是比较,那么其究竟是什么呢?

2.仿函数实现优先级队列

在实现堆的时候,对于大堆还是小堆的逻辑控制主要是使用push(向上调整算法)和pop(向下调整算法)时,判断父亲位置和孩子位置的大小关系,究竟是父亲大还是孩子大的关系。

对于大堆和小堆类,我们固然可以直接CV一份再将其符号修改,但是两个类的重合度极高,非常的臃肿。那么我们如何通过只实现一个类模板来完成大小堆的通用呢?

我们可以通过仿函数来实现。

仿函数

1.定义

通俗理解,仿函数是对于()的重载,从而达到仿照(类似)函数的行为。其本质就是运算符的重载。

2.语法

它的语法我们通过一个例子来进行演示。

template<class T>
struct Less
{
public:
    bool operator()(T x, T y)
    {
        return x < y;
    }
};

int main()
{
    Less<int> ls;
    cout << ls(1, 2) << endl; //这里和函数调用很类似
    return 0;
}

这里对于对象的使用就和调用函数。函数传参类型。

3.使用

那么我们如何使用仿函数来实现我们上述的需求呢?

以实现大堆的push为例。

//默认大堆的实现
void adjust_up(int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
        if (_con[parent] < _con[child])
		{
			swap(_con[child], _con[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

void push(const T& val)
{
	_con.push_back(val);
	adjust_up(_con.size() - 1);
}

对于上述的逻辑中,如果需要在一个类中实现大堆的逻辑,我们可以实现判断是否小于的仿函数,然后创建一个该类的对象,这样我们就可以通过该对象来实现仿函数进而替换上述中的比较逻辑。

template<class T>
struct less
{
	bool operator()(const T& x, const T& y)
	{
		return x < y;
	}
};
void adjust_up(int child)
{
	Compare com;
	int 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;
		}
	}
}

如果需要让大堆和小堆共用一个模板,那么如何控制其逻辑是大于还是小于呢?

我们可以使用模板参数,将仿函数对象作为模板传入,这样我们需要什么样的比较方式,就传入其对应的仿函数,从而让其自己实现比较逻辑。无论是内置类型还是自定义类型,只要我们实现了其逻辑的仿函数,都可以实现大小堆的排列。

template<class T>
struct less
{
	bool operator()(const T& x, const T& y)
	{
		return x < y;
	}
};

template<class T>
struct greater
{
	bool operator()(const T& x, const T& y)
	{
		return x > y;
	}
};
template<class T, class Container = vector<T>, class Compare = less<T>>
class priority_queue
{
public:
	void adjust_up(int child)
	{
		Compare com;
		int parent = (child - 1) / 2;
		while (child > 0)
		{
			if (com(_con[parent], _con[child]))
			{
				swap(_con[child], _con[parent]);
				child = parent;
				parent = (child - 1) / 2;
			}
			else
			{
				break;
			}
		}
	}

	void push(const T& val)
	{
		_con.push_back(val);
		adjust_up(_con.size() - 1);
	}
    //......
private:
    Container _con;

3.模拟实现源码

template<class T>
struct less
{
	bool operator()(const T& x, const T& y)
	{
		return x < y;
	}
};

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

template<class T, class Container = vector<T>, class Compare = less<T>>
class priority_queue
{
public:

	priority_queue()
	{

	}
	template <class InputIterator>
	priority_queue(InputIterator first, InputIterator last)
	{
		while (first != last)
		{
			push(*first);
			first++;
		}
	}

	void adjust_up(int child)
	{
		Compare com;
		int parent = (child - 1) / 2;
		while (child > 0)
		{
			//if (_con[child] > _con[parent])
			//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& val)
	{
		_con.push_back(val);
		adjust_up(_con.size() - 1);
	}

	void adjust_down(int parent)
	{
		Compare com;
		int child = parent * 2 + 1;
		while (child < _con.size())
		{
			if (child + 1 < _con.size() && com(_con[child], _con[child + 1]))
				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.front();
	}

	size_t size()
	{
		return _con.size();
	}

	bool empty() const
	{
		return _con.empty();
	}
private:
	Container _con;
};


	{
		swap(_con[0], _con[_con.size() - 1]);
		_con.pop_back();
		adjust_down(0);
	}

	const T& top() const
	{
		return _con.front();
	}

	size_t size()
	{
		return _con.size();
	}

	bool empty() const
	{
		return _con.empty();
	}
private:
	Container _con;
};
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值