关于最大堆与最小堆:
如果所有父节点的关键码都小于或等于孩子的关键码,则称最小堆。
如果所有父节点的关键码大于或等于孩子的关键码,则称最大堆。堆的性质:
1、可以通过一个简单的数组实现
2、支持最坏情况为O(logN)的insert和deleteMin
3、支持常量平均时间的insert操作以及常量平均最坏时间的findMin操作。
4、二叉堆是实现优先级队列的典型方法
template<typename T>
class BinaryHeap
{
typedef HeapNode<T> Node;
public:
BinaryHeap();
BinaryHeap(const vector<Node> &v);
void Insert(const Node& data);
void DeleteMin(Node& data = Node()); //删除最小元素,可以通过参数返回最小值
void MakeHeap(); //置空堆
bool IsEmpty()const; //判断堆是不是为空
const Node& findMin()const; //查找堆中的最小元素
protected:
void buildHeap(); //恢复堆的顺序
void percolate(int hole); //从hole开始下滑调整
protected:
vector<Node> _Heap; //存储的堆中元素的数组
int _Size; //标记堆中元素的个数
};
一、堆的建立
堆的建立有两种方式,一种是建立一个空堆,另一种是通过复制一个记录数组并对其加以调整形成一个堆。
时间复杂度:O(N*lgN)
二、Insert操作
Insert所需要的是上滑调整,直接向_Heap中插入数据,然后通过上滑调整顺序。
void Insert(const Node& data)
{
_Heap.push_back(data);
_Size++;
int i = _Size;
int parent= 0;
for (; i/2>0; i /= 2) //i这点的结点要有父亲节点
{
parent = i / 2; //父亲结点的位置
if (_Heap[parent] < data) //如果父亲结点比插入的值小,则有序
{
break;
}
else //如果父亲结点比插入值大
{
_Heap[i] = _Heap[parent];
}
}
_Heap[i] = data;
}
时间复杂度:O(lgN)
三、deleteMin操作
由于最小堆的性质,根节点总是最小值,所以将数组中最后一个结点的值放到根节点的位置,然后_Size自减,再从根节点开始进行一次下滑操作恢复堆的顺序。
void DeleteMin(Node& data=Node()) //删除最小元素,可以通过参数返回最小值
{
assert(_Size>0);
data = findMin();
_Heap[1] = _Heap[_Size--];
int i = 0;
percolate(1); //从根结点处开始下滑调整顺序
}
时间复杂度:O(lgN)
优先级队列:
#pragma once
#include"heap.h"
template<typename T,class Compare=Less<T> >
class PriQueue
{
public:
void Push(const T& x)
{
h.Push(x);
}
void Pop()
{
h.Pop();
}
const T& Top()
{
return h.Top();
}
private:
Heap<T, Compare> h;
};