堆:堆通常是一个可以被看做一棵树的数组对象
将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
//Heap
#include<vector>
#include<assert.h>
template<class T>
class Heap
{
public:
Heap()//无参
:_a(NULL)
{}
Heap(const T* a, int size)//带参的拷贝构造
{
for (int i = 0; i < size; i++)
{
_a.push_back(a[i]);//先压入栈中
}
//下调--从父节点找子节点
//int parent = (size - 1 - 1) / 2;
//从第一个有父节点的节点开始,每次都是向下找子节点,然后j--,慢慢的,
//调整到从最上面的节点向下调整
for (int j = (size - 1 - 1) / 2; j >= 0;j--)
{
_AdjustDown(j,size);
}
}
Heap(const Heap& vec)//拷贝构造
:_a(NULL)
{
_a.reserve(vec._a.size());//开辟同样一份空间
for (int i = 0; i < vec._a.size(); i++)
{
_a.push_back(vec._a[i]);//复制
}
}
void Push(const T& x)//push
{
_a.push_back(x);//先压入数据
_AdjustUp(_a.size() - 1);//然后进行向上调整
}
void Pop()//删除根节点,因为要删除根节点,所以删除_a[0]。
{
assert(_a.size() > 0);
swap(_a[0], _a[_a.size() - 1]);//与最后一个进行交换,
_a.pop_back();//然后调用pop_back()
_AdjustDown(0, _a.size());//从下标0,也就是根节点进行下调
}
void PrintHeap()
{
cout << "堆的序列为:" << endl;
for (int i = 0; i < _a.size(); i++)
{
cout << _a[i] << " ";
}
cout << endl;
}
T& GetTop()//得到根节点
{
assert(_a.size()>0);
return _a[0];
}
bool Empty()
{
return _a.size() == 0;
}
int Size()
{
assert(_a.size() >= 0);
return _a.size();
}
protected:
void _AdjustUp(int child)//向上调整,由子节点找父节点
{
int parent = (child - 1) / 2;//公式 -1再除2
while (parent >= 0)//由于是向上调整,所以调整到根节点结束
{
if (_a[child]>_a[parent])
{
swap(_a[child], _a[parent]);
child = parent;//继续调整
parent = (child - 1) / 2;
}
else//不大于就break
{
break;
}
}
}
//向下调整---从父节点找子节点
void _AdjustDown(int parent, int size)
{
int child = 2 * parent + 1;//算左孩子
while (child < size)
{
if (child + 1 < size&&_a[child + 1] > _a[child])
child++;//找左右孩子中较大的那个
if (_a[child]>_a[parent])
{
swap(_a[child], _a[parent]);
parent = child;//继续向下调整
child = 2 * parent + 1;
}
else//不大于就跳出循环
break;
}
}
protected:
vector<T> _a;
};
void Test()
{
int array[] = { 10, 11, 13, 12, 16, 18, 15, 17, 14, 19 };
Heap<int> hp1(array, sizeof(array) / sizeof(array[0]));
hp1.Push(20);
hp1.Pop();
hp1.PrintHeap();
Heap<int> hp2(hp1);
hp2.PrintHeap();
hp1.Push(20);
cout << hp1.GetTop() << endl;
hp1.Pop();
cout << hp1.GetTop() << endl;
}