堆是一颗被完全填满的二叉树,底层的元素从左到右填入。
所以一个高度为h的堆有2^h到2^(h+1)-1个节点,这样的堆可以用一个数组来表示,堆顶为arr[0],父节点的下标为n,左儿子的下标就是2n+1,
堆有大堆(父节点的值大于儿子节点的值)和小堆(父节点的值小于儿子节点的值),大堆的根节点就是数组中最大的值,小堆的根节点就是数组中最小的值。堆只能访问根节点,能进行插入和删除操作。
一共10个元素从第(10-1)/2 = 4开始对每个元素排序一直到排到根节点(第n-1),每个节点的排序按照从上到下的方式如果父节点大于儿子节点中较小的,则交换,否则对下一个元素排序(小堆)
#include <iostream>
using namespace std;
#include <vector>
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 arr[], size_t sz)
{
assert(arr);
for (int i = 0; i < sz; ++i)
_heap.push_back(arr[i]); //用容器存放元素
if (sz > 1)
for (int j = (sz - 1) / 2; j >= 0; --j)
{
_AdjustDown(j);
}
}
size_t Size()const
{
return _heap.size();
}
bool Empty()const
{
return _heap.empty();
}
void Insert(const T& data) //插入
{
_heap.push_back(data);
if (Size() > 1)
_AdjustUp(Size() - 1);
}
void Remove() //删除堆顶 (交换第一个和最后一个,将最后一个节点删除,对堆顶向下排序)
{
if (Empty())
return;
if (Size() == 1)
_heap.pop_back();
else
{
std::swap(_heap[0], _heap[Size() - 1]);
_heap.pop_back();
_AdjustDown(0);
}
}
protected:
void _AdjustDown(size_t parent)
{
size_t chlid = 2 * parent + 1;
while (chlid < _heap.size())
{
if (chlid + 1 < _heap.size())
chlid = ( Compare()(_heap[chlid], _heap[chlid+1])) ? chlid : (chlid + 1);
if (Compare()(_heap[parent], _heap[chlid]) )
std::swap(_heap[parent], _heap[chlid]);
parent = chlid;
chlid = 2 * parent + 1;
}
}
void _AdjustUp(size_t chlid)
{
size_t parent = (chlid - 1) / 2;
while (chlid != 0)
{
if ( Compare()(_heap[chlid], _heap[parent]))
std::swap(_heap[chlid], _heap[parent]);
else
break;
chlid = parent;
parent = (chlid - 1) / 2;
}
}
protected:
std::vector<T> _heap;
};
template <class T, class Compare = Less<T>> //用小堆构建优先级队列
class PriorityQueue {
public:
PriorityQueue()
:_hp()
{}
void Push(const T& data)
{
_hp.Insert(data);
}
void Pop()
{
_hp.Remove();
}
const T& Top()const
{
return _hp._heap[0];
}
size_t Size()const
{
return _hp.Size();
}
bool Empty()const
{
return _hp.Empty();
}
protected:
Heap<T, Compare > _hp;
};