堆是一种数据结构,它是一颗完全二叉树,最大堆和最小堆是二叉堆的两种形式。
最大堆:每个父亲结点的键值都大于孩子结点
最小堆:每个父亲结点的键值都小于孩子结点
下面看一下我的实现方式↓
#pragma once
#include
using namespace std;
template
struct Great
{
bool operator()(const T& left ,const T& right)const
{
return left > right;
}
};
template
struct Less
{
bool operator()(const T& left, const T& right)const
{
return left < right;
}
};
template
>
class Heap
{
public:
Heap()
{}
Heap(T* a, size_t n) //用一个数组构建堆的构造函数
{
_arr.reserve(n);
for (int i = 0; i < n; i++)
{
_arr.push_back(a[i]);
}
//调整堆
for (int i = (_arr.size() - 2) / 2; i >= 0; --i)
{
AdjustDown(i);
}
}
void AdjustDown(int root) //向下调整算法
{
Comp com;
int parent = root;
int child = parent * 2 + 1;
while (child < _arr.size())
{
if (child + 1 < _arr.size() && com(_arr[child + 1] , _arr[child]))
{
child++;
}
if (com(_arr[child],_arr[parent]))
{
swap(_arr[child], _arr[parent]);
parent = child; child = parent * 2 + 1;
}
else break; //循环到孩子小于父亲便可停止
}
}
void AdjustUp(int child) //向上调整算法
{
Comp com;
int parent = (child - 1) / 2;
while (parent >= 0)
{
if (com(_arr[child], _arr[parent]))
{
swap(_arr[parent], _arr[child]);
child = parent;
parent = (child - 1) / 2;
}
else
break;
}
}
void Push(const T& x) //从堆尾插入一个数据 (数组尾)
{
_arr.push_back(x);
AdjustUp(_arr.size() - 1);
}
void Pop() //删除堆顶数据 (数组头)
{
swap(_arr[0], _arr[_arr.size() - 1]);
_arr.pop_back();
AdjustDown(0);
}
size_t Size() //返回大小
{
return _arr.size();
}
bool Empty() //是否为空
{
return _arr.empty();
}
T& Top() //返回 堆顶数据
{
assert(_arr.size() > 0);
return _arr[0];
}
protected:
vector
_arr; //一个vector 堆的底层是一个数组; };
其中 向上调整与向下调整是建立一个最大最小堆的关键;调整时的比较大小是利用一个仿函数进行选择默认为大堆;
堆的作用挺大,比如优先级队列,top K问题 ,或者选择排序都用到堆的结构。