c++之priority_queue实现

priority_queue(优先级队列)

优先级队列的定义:优先级队列 是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优先权的元素。

实现原理:优先级队列默认的容器一般采用STL中的vector容器。因为vector具有高效的连续存储的效率,它的随机访问
的效率比较高,当然也可以采用stack或者dequeue,其它本身是一个堆的结构,默认条件下生成大堆

== 注意:优先级队列的实现的底层容器,默认采用vector,也可以采用dequeue,只是vector的随机访问效率较高,切记!!!千万不能使用list,因为list不支持随机访问!!! ==

优先级队列是一种新的数据结构,它能够快速的获取最大的,也可以通过pop操作获取第K大的数,而且时间复杂度
为O(1),它的默认为大堆,不过我们可以通过定义仿函数来实现大堆和小堆的变换。

仿函数

仿函数less的实现,必须重载()运算符
//仿函数类
//必须重载()运算符

template<class T>
struct Less
{
	bool operator()(const T& val1, const T& val2)
	{
		return val1 < val2;
	}
};
template<class T>
struct Greater
{
	bool operator()(const T& val1, const T& val2)
	{
		return val1 > val2;
	}
};
在实现完仿函数后,我们要在开始声明所用的泛型模板
template<class T, class Container=vector<T>,class Compare=Greater<T>>
对于Compare来说,这是一个定义比较规则的类,在compare里指定所要使用的规则,Less还是Greater,然后再在
priority_queue中创建对象_com,在节点比较的时候调用_com的()运算符,在这里大家可能听起来比较绕,下面
代码先码上

在这里插入图片描述

	//大堆向上调整
	void shiftUp(int child)
	{
		int parent = (child - 1) / 2;
		while (child > 0)
		{
			//if (_c[parent] < _c[child])
			if(_com(_c[parent], _c[child]))
			{
				swap(_c[parent], _c[child]);
				child = parent;
				parent = (child - 1) / 2;
			}
			else
				break;
		}
	}
这里的Greater用于建小堆,如果需要建大堆可以使用Less,这样的话就大大减小了代码的冗余度,减少了我们
写一些这种结构类似的代码,提高了效率,向传统的写法,我们至少得写两遍重复的代码,在这里我们使用了仿函数
重载()运算符,相当于在比较的时候调用了仿函数里面的()这个函数、

完整代码如下:

#include<iostream>
#include<list>
#include<vector>
#include<stack>
#include<deque>
using namespace std;


//仿函数类
//必须重载()运算符

template<class T>
struct Less
{
	bool operator()(const T& val1, const T& val2)
	{
		return val1 < val2;
	}
};

template<class T>
struct Greater
{
	bool operator()(const T& val1, const T& val2)
	{
		return val1 > val2;
	}
};



template<class T, class Container=vector<T>,class Compare=greater<T>>

class priorityQueue
{
public:

	//向上调整
	void shiftUp(int child)
	{
		int parent = (child - 1) / 2;
		while (child > 0)
		{
			//if (_c[parent] < _c[child])
			if(_com(_c[parent], _c[child]))
			{
				swap(_c[parent], _c[child]);
				child = parent;
				parent = (child - 1) / 2;
			}
			else
				break;
		}
	}

	void push(const T& val)
	{
		//尾插+向上调整
		_c.push_back(val);
		shiftUp(_c.size() - 1);
	}

	//向下调整
	void shiftDown(int parent)
	{
		int child = parent * 2+1;

		while (child < _c.size())
		{
			if (child + 1 < _c.size() &&_com(_c[child] , _c[child + 1] ))
			{
				child++;
			}
			if(_com(_c[parent] , _c[child]))
			//if (_c[parent] < _c[child])
			{
				swap(_c[parent], _c[child]);
				parent = child;
				child = parent * 2 + 1;
			}
			else
				break;
		}
	}

	//删除堆顶元素  交换首尾元素,向下调整
	void pop()
	{
		swap(_c[0], _c[_c.size() - 1]);
		_c.pop_back();
		shiftDown(0);


	}

	T& top()
	{
		//return _c[0];
		return _c.front();
	}

	bool empty()
	{
		return _c.empty();
	}

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

private:
	Container _c;
	Compare _com;
};

void test()
{
	//大堆
	//优先级队列的默认容器:vector,vector--->随机访问的效率高于双端队列
	
	//priorityQueue<int, vector<int>,less<int>> pq;
	//小堆
	priorityQueue<int, vector<int>, greater<int>> pq;

	//priorityQueue<int, deque<int>> pq;
	//list不支持随机访问,不能做优先级队列的底层容器
	//priorityQueue<int, list<int>> pq;
	pq.push(1);
	pq.push(5);
	pq.push(23);
	pq.push(32);
	pq.push(10);



}

//int main()
//{
//	test();
//	return 0;
//}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值