这一节我们来讲一讲优先级队列,但是我们得先引入一个概念,那就是仿函数。
首先我们来看看仿函数。
我们在c语言中学习过了函数指针,但是用函数指针的话,会涉及到一个回调函数的问题,使用起来会有些麻烦。所以在c++中我们引入了一个叫做仿函数的概念。他是在类中定义的一个重载函数,但是他有点特别,他重载的运算符是(),具体怎么使用的呢,我们来看:
可以看到,我们结合模板,可以实现仿函数的效果。本质上我们调用的函数是这个:
但通过运算符重载我们就可以直接写成前者的模式了。
有了仿函数的基础后,我们就要看一看优先级队列是怎么实现的了。
首先我们要明白,优先级队列就是一个大堆,其中选择大堆还是小堆,要自己传容器,如果没有就是默认为大堆。剩下的就是简单的堆实现了,之前的堆排也涉及了一些,但是今天我们要实现的是实现优先级队列中主要的部分。
template <class T, class Container = vector<T>, class Compare = less<T> >
class priority_queue
{
public:
void AdjustUp(int child)
{
int parent = (child - 1) / 2;
while (parent >= 0)
{
if (comp(c[child], c[parent]))
swap(c[child], c[parent]);
else
break;
child = parent;
parent = (child - 1) / 2;
}
}
void AdjustDown(int parent)
{
int child = parent * 2 + 1;
while (child < c.size())
{
if (child + 1 < c.size() && comp(c[child + 1], c[child]))
{
child++;
}
if (comp(c[child], c[parent]))
{
swap(c[child] , c[parent]);
}
parent = child;
child = parent * 2 + 1;
}
}
priority_queue()
{}
template <class InputIterator>
priority_queue(InputIterator first, InputIterator last)
{
InputIterator it = first;
while (it != last)
{
c.push_back(*it);
AdjustUp(c.size() - 1);
it++;
}
}
bool empty() const
{
return c.empty();
}
size_t size() const
{
return c.size();
}
const T& top() const
{
return c[0];
}
void push(const T& x)
{
c.push_back(x);
AdjustUp(c.size() - 1);
}
void pop()
{
swap(c[0], c[c.size() - 1]);
c.pop_back();
AdjustDown(0);
}
private:
Container c;
Compare comp;
};
其中less我们传进去的就是Less<T>。这样我们的优先级队列就实现了,这个不管是排序还是查找,时间复杂度都非常低,是个不错的数据结构。