1、优先级队列是一个容器适配器,功能是能根据预先设定规则,在插入时将元素排列,如让元素升序降序等,采用的数据结构时堆,底层是vector(也可以用用户自己设计的序列式容器)。以下是一个优先级队列的简易实现,包含一个堆的向下调整及向上调整函数,以及仿函数的利用。
#include<iostream>
#include<vector>
using namespace std;
namespace k
{
template<class T>
struct less
{
bool operator()(T& a, T& b)
{
return a < b;
}
};
template<class T>
struct greater
{
bool operator()(T& a, T& b)
{
return a > b;
}
};
template<class T, class Container = vector<T>, class Compare = less<T>>
class priority_queue
{
public:
void AdjustUp(int child)
{
Compare cpr;
while (child)
{
int prt = (child - 1) / 2;
if (cpr(_con[prt], _con[child]))
{
swap(_con[child], _con[prt]);
}
else
{
break;
}
child = prt;
}
}
void AdjustDown(int prt)
{
Compare cpr;
int child = prt * 2 + 1;
while (child < _con.size())
{
if (child + 1 < _con.size() && cpr(_con[child], _con[child + 1]))
{
child++;
}
if (cpr(_con[prt], _con[child]))
{
swap(_con[prt], _con[child]);
prt = child;
child = prt * 2 + 1;
}
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);
}
size_t size()
{
return _con.size();
}
bool empty()
{
return _con.empty();
}
T top()
{
return _con[0];
}
private:
Container _con;
};
}
可以看到priority_queue有三个模板参数,第一个是元素类型T,第二个是容器类型container,第三个是用于进行比较的仿函数的类型,有大于和小于,通过控制仿函数的类型,我们可以控制vector是大堆还是小堆。
2、什么是仿函数?
仿函数又叫函数对象,因为单看他的使用,你会以为他是一个函数,实际上是设计了一个类,这个类一般没有成员变量(所以类的大小为1字节),并且为这个类重载了括号运算符用于实现一些计算。如上面的优先级队列的仿函数,实现了两个,大于和小于,在用于比较时,定义一个仿函数对象,直接调用operator()即可。