堆的建立、插入与删除
堆的储存结构
堆使用完全二叉树的结构进行储存,根据完全二叉树的性质,在堆中给定下标为i的节点时:
- 如果i=0,节点i是根节点;否则节点i的父节点为节点(i-1)/2
- 如果2i+1>n-1,则节点i无左子女;否则节点i的左子女为2i+1
- 如果2i+2>n-1,则节点i无右子女;否则节点i的右子女为2i+2
堆元素使用的结构体定义
typedef struct Message {
char Msg[20]; //命令名称
int K; //优先级
friend bool operator>(Message& A, Message& B);
friend bool operator<=(Message& A, Message& B);
}E;
MinHeap的类成员
#define DefaultSize 100000
class MinHeap
{
private:
E* heap; //存放最小堆中元素的数组
int currentSize; //最小堆中当前元素数量
int maxHeapSize; //最小堆能容纳的最大数量
public:
MinHeap(int sz = DefaultSize); //构造函数
~MinHeap() { delete[] heap; } //析构函数
bool Insert(const E& x); //将x插入到最小堆中
bool Remove(E& x); //删除堆顶元素,并通过x返回
private:
void siftDown(int start, int m); //从start到m下滑调整成为最小堆
void siftUp(int start); //从start到0向上调整成为最小堆
};
MinHeap的成员函数
1.构造函数,创建一个sz大小的数组空间,初始化数组大小为0,通过插入操作对堆进行赋值
MinHeap::MinHeap(int sz)
{
//动态建立数组空间
maxHeapSize = ( DefaultSize < sz) ? sz : DefaultSize;
heap = new E[maxHeapSize]; //创建储存空间
if (heap == NULL) {
cerr << "储存分配失败" << endl; exit(1);
}
currentSize = 0; //建立当前大小
}
2.siftdown函数
void MinHeap::siftDown(int start, int m)
{
//从节点start开始到m为止,自上向下比较,如果子女的值小于父节点的值
//则关键码小的上浮,继续向下层比较,这样将一个集合局部调整为最小堆
int i = start, j = i * 2 + 1; //j是i的左子女
E temp = heap[i]; //将start中的元素存放到临时空间中
while (j <= m) {
if (j<m && heap[j]>heap[j + 1]) {
j++; //如果右子树比左子树小,则将j指向右子树
}
if (temp <= heap[j]) break; //如果根节点比子女小,则不做调整
else {
heap[i] = heap[j]; //否则小的上移
i = j;
j = j * 2 + 1; //i,j下移
}
}
heap[i] = temp; //回放temp中暂存的元素
}
3.siftup函数
void MinHeap::siftUp(int start)
{
//从节点start开始向0调整,自下而上比较,如果子女的值小于父节点的值
//则交换,小的上移,这样将集合调整为最小堆
int j = start;
int i = (j - 1) / 2; //i是j的父节点
E temp = heap[j];
while (j > 0) { //沿父节点路径向上直达根
if (heap[i] <= temp) break; //父节点的值小,不作调整
else {
heap[j] = heap[i]; //父节点的值大,用父节点的值替代子女节点的值
j = i; i = (i - 1) / 2; //i,j上移
}
}
heap[j] = temp; //回送
}
4.MinHeap的插入函数
bool MinHeap::Insert(const E& x)
{
//将x插入到最小堆中
if (currentSize == DefaultSize) {
cerr << "Heap Full" << endl; return false; //堆满
}
heap[currentSize] = x; //插入
siftUp(currentSize); //向上调整
currentSize++; //堆计数加1
return true;
}
5.MinHeap的删除函数
bool MinHeap::Remove(E& x)
{
if (!currentSize) {
//cout << "Heap empty" << endl;
return false; //堆空
}
x = heap[0]; heap[0] = heap[currentSize - 1]; //返回并删除堆顶元素,用最后一个元素填补根节点
currentSize--; //最小堆计数减1
siftDown(0, currentSize - 1); //自上而下调整最小堆
return true;
}