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;
//}