优先级队列介绍和模拟实现

个人主页:Lei宝啊 

愿所有美好如期而遇


Container就是适配器,也就是说这个优先级队列的底层就使用vector,当然,我们也可以使用deque来适配,但是对于优先级队列来说,效率是低于vector的,因为优先级队列本质就是堆,我们需要用到下标来进行向上或者向下调整,而deque虽然可以使用下标索引,同时也具备链式结构,但是单独拉出来一个功能效率是不如vector和queue的,所以使用deque适配的效率不如vector,同时这里是不能用queue来适配的。

上面我们也可以看见Compare默认是less,也就是说优先级队列默认是建大堆的(尽管使用less建大堆,greater建小堆看着很难受,但库就是这么实现的)。

push方法,就是向优先级队列里插入元素,同时调整成堆,pop方法,就是删除堆顶元素,同时向下调整维持堆的结构。

其他方法我们不多赘述,接下来开始模拟实现优先级队列。

首先将Compare仿函数实现出来,这里就要介绍什么是仿函数:

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

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

我们平时调用函数时是这样:比如有一个int add(int a,int b)函数,我们调用时是这样add(1,2),那么仿函数就是:类里重载了()运算符的operator(),使得这个类使用起来像一个函数。

我们使用时先创建这个类的对象,比如Less compare; 然后比较大小就是这样:compare(1,2),是不是很类似于函数?

接着就是优先级队列的内部构造:

其中的核心也就是堆向上调整,堆向下调整,数据的插入和删除,也就这么四个核心点,type就是我们要适配的容器。

	//默认建大堆
	template<class T, class type = vector<int>, class compare = Less<T>>
	class priority_queue
	{
	public:
		priority_queue() {};

		template <class InputIterator>
		priority_queue(InputIterator first, InputIterator last)
		{
			while (first != last)
			{
				q.push_back(*first);
				judge_up(size() - 1);

				first++;
			}
		}

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

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

		T& top()
		{
			return q.front();
		}

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

		void judge_up(int child)
		{
			int parent = (child - 1) / 2;

			while (child)
			{
				if (com(q[child], q[parent]))
				{
					swap(q[child], q[parent]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}

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

		void judge_down(int parent)
		{
					
			int child = parent * 2 + 1;
			
			while (child < size())
			{
				if (child + 1 < size() && !com(q[child], q[child + 1]))
				{
					child++;
				}

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

		void pop()
		{
			swap(q[0], q[size() - 1]);
			q.erase(q.end() - 1);
			judge_down(0);
		}

	private:
		type q;
		compare com;
	};

}

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lei宝啊

觉得博主写的有用就鼓励一下吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值