
#define DefaultSize 10;
template <class E> //堆中存储的是一个记录的集合,并根据每个记录的关键码以最小堆序排序,在使用堆操作之前需要定义记录的结构类型,用E表示
class MinHeap:public PQueue<E>{
//最小堆类继承了最小优先级队列
public:
MinHeap(int sz=DefaultSize);
MinHeap(E arr[],int n);
~MinHeap(){delete []heap};
bool Insert(const E& x);
bool RemoveMin(E& x);
bool IsEmpty()const{return currentSize==0;}
bool IsFull()const{return currentSize==maxHeapSize;}
void MakeEmpty(){currentSize=0;}
private:
E *heap;
int currentSize;
int maxHeapSize;
void siftDown(int start,int m);
void siftUp(int start);
}
template <class T>
MinHeap<E>::MinHeap(int sz=DefaultSize){
maxHeapSize=(DefaultSize<sz)?sz:DefaultSize;
heap=new E[maxHeapSize];
if(heap==NULL){
cerr<<"堆存储分配失败!"<<endl;
exit(1);
}
currentSize=0;
}
template <class T>
MinHeap<E>::MinHeap(E arr[],int n){ //复制构造函数,数组调整成堆
maxHeapSize=(DefaultSize<n)?n:DefaultSize; //取n和DefaultSize中比较大的一个作为最小堆的大小
heap=new E[maxHeapSize];
if(heap==NULL){
cerr<<"堆分配存储失败!"<<endl;
exit(1);
}
for(int i=0;i<n;i++) heap[i]=arr[i];
currentSize=n;
int currentPos=(currentSize-2)/2; //找最初调整位置:最后分支结点(最后一个结点的父结点)
while(currentPos>=0){ //自底向上逐步扩大成堆
siftDown(currentPos,currentSize-1); //局部自上向下下滑调整
currentPos--; //再向前换一个分支结点
}
}
template <class T>
void MinHeap<E>::siftDown(int start,int m){
//私有函数,从结点start开始到m为止,自上而下比较,如果子女的值小于父结点的值,则关键码小的上浮,继续向下层比较,这样将一个集合局部调整为最小堆
int i=start,j=2*i+1; //j指向i的左子女
E temp=heap[i];
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=2*j+1;
}
}
heap[i]=temp;
}
template <class E>
void MinHeap<E>::siftUp(int start){
//私有函数:从结点start开始到结点0为止,自下而上比较,如果子女的值小于父结点的值则相互交换,这样将集合重新调整为最小堆,关键码比较符<=在E的类型中定义
int j=start,i=(j-1)/2; //j指向i的父结点
E temp=heap[j];
while(j>0){
if(heap[i]<=temp)break;
else{
heap[j]=heap[i];
j=i;
i=(i-1)/2;
}
}
heap[j]=temp;
}
template <class E>
bool MinHeap<E>::Insert(const E& x){
if(currentSize==maxHeapSize){
cerr<<"Heap Full"<<endl;
return false;
}
heap[currentSize]=x;
siftUp(currentSize); //向上调整
currentSize++;
return true;
}
template <class E>
bool MinHeap<E>::RemoveMin(E &x){
if(!currentSize){
cout<<"Heap empty"<<endl;
return false;
}
x=heap[0];
heap[0]=heap[currentSize-1];
currentSize--;
siftDown(0,currentSize-1);
return true;
}