首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >C++:模拟实现priority_queue

C++:模拟实现priority_queue

作者头像
HZzzzzLu
发布2024-11-26 08:22:35
发布2024-11-26 08:22:35
18600
代码可运行
举报
文章被收录于专栏:codingcoding
运行总次数:0
代码可运行

priority_queue的介绍

概念

在C++标准库中,priority_queue是一个基于优先级堆的容器适配器。它的底层容器是vector,将其封装成堆来管理元素,确保元素按照特定的优先级顺序排列。

默认情况下,priority_queue是大堆,因为其的比较函数是std::less,如果想要建立小堆,则使用std::greater比较函数,这个比较函数其实是仿函数,接下来会提及。

特点

1.自动排序

元素根据优先级自动排序,最高优先级的元素总是在队列的前端。

2.只访问前端元素

只能访问队列的前端元素,即最高优先级的元素。

3.底层容器

使用vector作为底层容器来存储元素,但用户不能直接访问这个容器。

4.元素比较

priority_queue需要一个比较函数或函数对象来确定元素的优先级顺序默认情况下使用std:less,即最大值优先。

priority_queue的使用

基本操作

  • empty():检查队列是否为空。
  • size():返回队列中的元素数量。
  • top()访问队列前端的元素(不删除)。
  • pop()移除队列前端的元素。
  • push():向队列添加新元素。

演示代码

代码语言:javascript
代码运行次数:0
运行
复制
int main()
{
	std::priority_queue<int, vector<int>, less<int>> pq;
	pq.push(2);
	pq.push(1);
	pq.push(4);
	pq.push(5);
	pq.push(3);

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

	return 0;
}

priority_queue的模拟实现

仿函数

要想实现priority_queue,我们首先需要了解仿函数。

在 C++ 中,仿函数(Functor)是一种重载了函数调用操作符 operator() 的类或结构体。仿函数可以像函数一样被调用,但它们实际上是对象,因此可以拥有成员变和成员函数。

仿函数是函数对象(function object)的一种,它们通常用于需要函数指针或函数引用的地方,尤其是当需要传递具有特定行为的对象时

仿函数的一些关键特性:

  1. 重载 operator(): 仿函数必须重载函数调用操作符 operator(),使其能够像函数一样被调用。
  2. 状态存储: 仿函数可以拥有自己的数据成员,这些成员存储了仿函数的状态。
  3. 行为封装: 仿函数可以封装特定的行为,这些行为可以通过其 operator() 实现。
  4. 灵活性: 仿函数提供了比普通函数更多的灵活性,因为它们可以存储状态,并且可以被重载。
  5. STL 兼容性: 仿函数与 STL 容器和算法兼容,可以作为算法的参数传递。

仿函数的简单示例

上面我们提到std::less就是一个仿函数,我们就来模拟实现下。

代码语言:javascript
代码运行次数:0
运行
复制
template<class T>
class Less
{
public:
	bool operator()(const T& x, const T& y)
	{
		return x < y;
	}
};

向上调整和向下调整

我们知道priority_queue其实是堆,既然是堆那就需要实现向上调整和向下调整算法。

代码语言:javascript
代码运行次数:0
运行
复制
void AdjustDown(int parent)
{
	int child = 2 * parent + 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[parent], _con[child]);
			parent = child;
			child = 2 * parent + 1;
		}
		else
		{
			break;
		}
	}
}

void AdjustUp(int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (_com(_con[parent], _con[child]))
		{
			swap(_con[parent], _con[child]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

模拟实现的代码

代码语言:javascript
代码运行次数:0
运行
复制
template<class T>
class Less
{
public:
	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 AdjustDown(int parent)
	{
		int child = 2 * parent + 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[parent], _con[child]);
				parent = child;
				child = 2 * parent + 1;
			}
			else
			{
				break;
			}
		}
	}

	void AdjustUp(int child)
	{
		int parent = (child - 1) / 2;
		while (child > 0)
		{
			if (_com(_con[parent], _con[child]))
			{
				swap(_con[parent], _con[child]);
				child = parent;
				parent = (child - 1) / 2;
			}
			else
			{
				break;
			}
		}
	}

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

	//删除堆顶的元素
	void pop()
	{
		swap(_con[0], _con[_con.size() - 1]);
		_con.pop_back();
		AdjustDown(0);
	}

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

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

	int size() const
	{
		return _con.size();
	}


private:
	Container _con;
	Compare _com;
};

拜拜,下期再见😏

摸鱼ing😴✨🎞

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-11-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • priority_queue的介绍
    • 概念
    • 特点
  • priority_queue的使用
    • 基本操作
    • 演示代码
  • priority_queue的模拟实现
    • 仿函数
    • 向上调整和向下调整
    • 模拟实现的代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档