优先级队列是在堆的基础上进行的一个扩展,主要是运用大堆来实现优先级队列,让优先度高的出队列,最大优先队列可以选用大堆,最小优先队列可以选用小堆来实现。
下面以最大优先队列来讲解其原理。
最大优先队列一般包括将一个元素插入到集合S中、返回集合S中具有最大key的元素、返回并删除集合S中具有最大key的元素等。
堆的实现代码如下
下面给出实现代码:
#include <vector>
#include <assert.h>
using namespace std;
template<class T>
struct Less
{
bool operator()(const T& left, const T& right)
{
return left < right;
}
};
template<class T>
struct Greater
{
bool operator()(const T& left, const T& right)
{
return left > right;
}
};
template<class T, class Compare = Less<T>>
class Heap
{
public:
Heap()
{}
Heap(const T array[], size_t size)
{
_heap.reserve(size);
for (size_t i = 0; i < size; i++)
{
_heap.push_back(array[i]);
}
for (int j = (_heap.size() - 2) / 2; j >= 0; j--)
{
_AdjustDown(j);
}
}
void Insert(const T& data)
{
assert(data);
assert(!_heap.empty());
_heap.push_back(data);
_Adjustup(_heap.size() - 1);
}
void Remove()
{
assert(!_heap.empty());
swap(_heap[0], _heap[size() - 1]);
_heap.pop_back();
_AdjustDown(0);
}
void Push(const T& x)
{
//插入到尾部,再从最后一个元素开始向上调整
_a.push_back(x);
AdjustUp(_a.size()-1);
}
void Pop()
{
//将堆顶与最后一个元素交换,再从堆顶下滑调整
assert(!_a.empty());
swap(_a[0], _a[_a.size() - 1]);
_a.pop_back();
if (_a.size()>1) //如果堆中的元素大于一个,再进行调整
{
AdjustDown(0, _a.size());
}
}
size_t Size()const
{
return _heap.size();
}
bool Empty()const
{
return _heap.empty();
}
const T& Top()const
{
assert(!_heap());
return _heap[0];
}
void _AdjustDown(size_t parent)
{
assert(parent);
assert(!_heap.empty());
size_t child = parent * 2 - 1;
while (parent < _heap.size())
{
Compare com;
if (child + 1<_heap.size()&& com(_heap[child + 1], _heap[child]))
{
++child;
}
if (child<_heap.size() && com(_heap[child], _heap[parent]))
{
swap(_heap[child], _heap[parent]);
parent = child;
child = parent * 2 + 1;
}
else
break;
}
}
void _AdjustUp(size_t child)
{
assert(!_heap.empty());
while(child)
{
Compare com;
size_t parent = (child - 1) / 2;
if (com(_heap[child], _heap[parent]))
{
swap(_heap[child], _heap[parent]);
child = parent;
}
else
break;
}
}
private:
vector<T> _heap;
};
template<class T, class Compare = Less<T>>
class PriorityQueue
{
public:
PriorityQueue()
{}
PriorityQueue(T* a, size_t size)
:_h(a, size)
{
}
void Push(const T& data)
{
_hp.push(data);
}
void Pop()
{
_hp.pop();
}
const T& Top()const
{
_hp.Top();
}
size_t Size()const
{
return _heap.size();
}
bool Empty()const
{
return _hp.Empty();
}
protected:
Heap<T, Compare> _hp;
};