#ifndef _MINHEAP_H
#define _MINHEAP_H
template <class T>
class MinHeap //最小堆ADT定义
{
private:
T* heapArray; //存放堆数据的数组
int CurrentSize; //当前堆中元素数目
int MaxSize; //堆所能容纳的最大元素数目
void BuildHeap(); //建堆
public:
//构造函数,n表示初始化堆的最大元素数目
MinHeap(const int n,const T* array, int size);
//析构函数
virtual ~MinHeap()
{
delete []heapArray;
}
//如果是叶结点,返回TRUE
bool isLeaf(int pos) const;
//返回左孩子位置
int leftchild(int pos) const;
//返回右孩子位置
int rightchild(int pos) const;
// 返回父结点位置
int parent(int pos) const;
// 删除给定下标的元素
bool Remove(int pos, T& node);
//向堆中插入新元素newNode
bool Insert(const T& newNode);
//从堆顶删除最小值
T& RemoveMin();
//从position向上开始调整,使序列成为堆
void SiftUp(int position);
//筛选法函数,参数left表示开始处理的数组下标
void SiftDown(int left);
};
template<class T>
MinHeap<T>::MinHeap(const int n,const T* array, int size)
{
if(n<=0||size>n)
return;
CurrentSize=0;
MaxSize=n;//初始化堆容量为n
heapArray=new T[MaxSize];//创建堆空间
//此处进行堆元素的赋值工作
//要为heapArray数组进行一些赋值,不然
//无法实现建堆操作,因为CurrentSize为0
for(int i=0; i<size; i++)
{
heapArray[i]=array[i];
}
CurrentSize = size;
BuildHeap();
}
//建堆
template<class T>
void MinHeap<T>::BuildHeap()
{
//反复调用筛选函数,问题:CurrentSize<2?
for (int i=CurrentSize/2-1; i>=0; i--)
SiftDown(i);
}
//筛选法函数,参数left表示开始处理的数组下标
template <class T>
void MinHeap<T>::SiftDown(int position)
{
int i=position;//标识父结点
//此时j不一定是关键值较小的子结点,
//但是希望它标识关键值较小的子结点。
int j=2*i+1;
T temp=heapArray[i];//保存父结点
//过筛
while(j<CurrentSize){
if((j<CurrentSize-1)&&(heapArray[j]>heapArray[j+1]))
{
//while第一次循环时,如果进入,比较左结点和右结点的值
//如果左结点的值大于右结点的值则,j指向数值较小的子结点
j++;
}
if(temp>heapArray[j]){
heapArray[i]=heapArray[j];
i=j;
j=2*j+1;//向下继续
}//end if
else
break;
}//end if
heapArray[i]=temp;
}
//如果是叶结点,返回TRUE
template<class T>
bool MinHeap<T>::isLeaf(int pos) const
{
return (pos>=CurrentSize/2)&&(pos<CurrentSize);
}
//返回左孩子位置
template<class T>
int MinHeap<T>::leftchild(int pos) const
{
return 2*pos+1;//返回左孩子位置
}
//返回右孩子位置
template<class T>
int MinHeap<T>::rightchild(int pos) const
{
return 2*pos+2;//返回右孩子位置
}
// 返回父结点位置
template<class T>
int MinHeap<T>::parent(int pos) const
{
return (pos-1)/2;//返回父结点位置
}
//向堆中插入新元素newNode
template <class T>
bool MinHeap<T>::Insert(const T& newNode)
{
if(CurrentSize == MaxSize)//堆空间已经满
return false;
heapArray[CurrentSize]=newNode;
SiftUp(CurrentSize);//向上调整
CurrentSize++;
}
//从position向上开始调整,使序列成为堆
template<class T>
void MinHeap<T>::SiftUp(int position)
{
int temppos=position;
T temp=heapArray[temppos];
//请比较父子结点直接swap的方法
while((temppos>0)&&(heapArray[parent(temppos)]>temp))
{
heapArray[temppos]=heapArray[parent(temppos)];
temppos=parent(temppos);
}
heapArray[temppos]=temp;
}
//从堆顶删除最小值
template<class T>
T& MinHeap<T>::RemoveMin()
{
if(CurrentSize==0)
{
//空堆
cout<<"Can't Delete";
exit(1);
}
else
{
//交换堆顶和最后一个元素
swap(0,--CurrentSize);
if(CurrentSize>1) // <=1就不要调整了
//从堆顶开始筛选
SiftDown(0);
return heapSize[CurrentSize];
}//end else
}
// 删除给定下标的元素
template<class T>
bool MinHeap<T>::Remove(int pos, T& node)
{// 删除给定下标的元素
if((pos<0)||(pos>=CurrentSize))
return false;
//指定元素置于最后
T temp=heapArray[pos];
heapArray[pos]=heapArray[--CurrentSize];
SiftUp(pos);//上升筛
SiftDown(pos);//向下筛,不是SiftDown(0);
node=temp;
return true;
}
#endif
调用
#include "MinHeap.h"
#include <stdio.h>
void main()
{
int array[10]={10,9,8,7,6,5,4,3,2,1};
MinHeap<int>* heap = new MinHeap<int>(20,array,10);
int node = 4;
heap->Insert(node);
delete heap;
heap = NULL;
}
//参考北京大学张铭ppt