/*
** 小根堆的实现
** 逻辑模型是一个完全二叉树 存储模型是给vector
** 索引下标从0开始
**(1)如果i=0,结点i是根结点,无父结点;否则结点i的父结点为结点(i-1)/2;
**(2)如果2i+1>n-1,则结点i无左子女;否则结点i的左子女为结点2i+1;
**(3)如果2i+2>n-1,则结点i无右子女;否则结点i的右子女为结点2i+2
** 插入一个元素:新元素被加入到heap的末尾,然后更新树以恢复堆的次序。从下往上调整
** 删除一个元素:为了便于重建堆,实际的操作是将最后一个数据的值赋给根结点,堆的元素个数-1,然后再从根结点开始进行一次从上向下的调整。
*/
namespace myHeap {
template <typename T>
class MinHeap
{
private:
unsigned int maxNodeNum, curSize;
std::vector<T> heapDatas;
public:
MinHeap(unsigned int _max):
maxNodeNum(_max),
curSize(0)
{
//索引下表从0开始
heapDatas.assign(maxNodeNum - 1,0);
}
MinHeap(std::vector<T> _data)
{
maxNodeNum = _data.size();
heapDatas.assign(maxNodeNum, 0);
for (auto i = _data.begin(); i != _data.end(); i++)
{
insert(*i);
}
}
void insert(T value)
{
assert(curSize + 1 <= maxNodeNum);
++curSize;
heapDatas[curSize-1] = value;
recorderUpwards(curSize-1);
}
T pop()
{
assert(!empty());
swap(0, curSize-1);
--curSize;
if (!curSize)
return heapDatas[curSize];
//从上往下调整堆,最后一个元素不要调整了,pop出去
recorderDownwards(0, curSize-1);
//print();
return heapDatas[curSize];
}
void swap(const int i,const int j)
{
T temp = heapDatas[i];
heapDatas[i] = heapDatas[j];
heapDatas[j] = temp;
}
//插入数据需要从下向上调整
//index 从index一直调整到0
void recorderUpwards(uint index)
{
while (index>0 && heapDatas[(index-1)/2]>heapDatas[index])
{
swap(index, (index - 1) / 2);
index = (index - 1) / 2;
}
}
//删除数据从上向下调整
//从begin位置调整到end位置
void recorderDownwards(uint begin,uint end)
{
while (2*begin+1 <= end)
{
uint child = 2 * begin + 1;
//取两个子节点中比较小的进行比较调换
if ((child < end) && (heapDatas[child] > heapDatas[child+1]))
child++;
if (child <= end)
{
if (heapDatas[begin] > heapDatas[child])
{
swap(begin, child);
begin = child;
}
else
break;
}
else
break;
}
}
bool empty() { return curSize == 0; }
void print()
{
for (int i = 0; i < getSize(); i++)
{
std::cout << heapDatas[i] << " ";
}
std::cout << std::endl;
}
std::vector<T>& get() { return heapDatas; } const
uint getSize() { return curSize; }
};
void test()
{
std::vector<int> v = { 1,4,6,2,3,8, 2,11,123,13,24,13,14,14 };
MinHeap<int> h(v);
h.print();
auto datas = h.get();
uint size = h.getSize();
for (uint i = 0; i < size; i++)
{
std::cout << "pop:" << h.pop() << std::endl;
}
std::cout << std::endl;
}