堆的定义
采用完全二叉树储存的优先队列称为堆
将该二叉树的宽度优先遍历储存在数组中
完全二叉树:编号为i的结点与完全二叉树编号为i的结点位置相同
在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征
最大堆
根节点到任一结点的关键字序列保持非递增
最小堆
根节点到任一结点的关键字序列保持非递减
堆的操作
创建
struct HNode{
int *Data;//储存元素的数组
int Size;//堆中当前元素的个数
int Capacity;//堆的最大容量
}
typedef struct HNode* Heap;
typedef Heap MaxHeap;
MaxHeap CreateHeap(int MaxSize){
//容量为Maxsize的空的最大堆
MaxHeap h=(MaxHeap)malloc(sizeof(struct HNode));
h->Data=(int*)malloc((Maxsize+1)*sizeof(int));
h->Size=0;
h->Capacity=Maxsize;
h->Data[0]=INT_MAX;//换成INT_MIN同样适用于最小堆,Data[0]作为哨兵不记录值
return h;
}
插入
新增节点先存入数组末尾,然后向上渗透
bool insert(MaxHeap h, int x){
int i;
if(IsFull(h){
printf("最大堆已满");
return false;
}
i=+++h->Size;//i指向堆中数组的最后一个位置
for(;h->Data[i/2]<x;i/2){//每次和该节点的父节点进行比较
h->Data[i]=h->Data[i/2];//向上渗透
}
h->Data[i]=x;//插入x
return true;
}
删除
总是最先删除根结点
删除的过程中要保持完全二叉树的结构特性
int DeleteMax(MaxHeap h){
//从最大堆取出根结点(最大的元素),并删除一个结点
int parent child;
int maxItem x;
if(IsEmpty(h)){
printf("最大堆已满");
return ERROR;
}
MaxItem=h->Data[1];//取出根结点中存放的最大值
//只能取末尾元素作为新的根结点,否则不是完全二叉树
x=h->Data[h->Size--];//取出末尾元素,并将堆大小减一
//将x作为新的根从根节点开始下滤,将数组中的元素重新排列
for(parent=1;parent*2<=h->Size;parent=child){
child=parent*2;
if(child!=h->size && h->Data[child] < h->Data[child])
//上浮的结点必须是较大的子结点,否则从上到下遍历时不满足最大堆(如果较小结点a上浮,则从上向下遍历时,a<较大子结点b)
child++;//child指向左右子结点较大者或惟一结点
if(x >= h->Data[child])
break;//找到合适位置
else//下滤x
h->Data[parent]=h->Data[child];
}
h->Data[parent]=x;
return MaxItem;
}
建立
将已存在的n个元素按照最大堆的要求存放在一个一维数组中
方法一:通过最大堆的插入操作将n个元素相继插入空的堆中去
方法二:
1,将n个元素按顺序存入二叉树中,只满足完全二叉树的结构特性即可
2,调整各结点元素,以满足最大堆的有序性
void PercDown(MaxHeap h, int p){
//下滤,将以h->Data[p]为根的子堆调整为最大堆
int parent,child;
int x;
x=h->Data[p];
for(parent=p;parent*2 <= h->Size;parent=child){
child=parent*2;
if(child != h->Size && h->Data[child] < h->Data[child+1])
child++;//child指向左右结点较大值
if(x >= h->Data[child])
break;//找到了合适的位置
else
h->Data[parent]=h->Data[child];//下滤x
}
h->Data[parent]=x;
}
void BUildHeap(MaxHeap h){
//调整h->Data[]中的元素,满足最大堆的有序性
int i;
//从最后一个结点的父节点开始,到根结点1
for(i=h->Size/2;i>0;i--){
PercDown(h,i);
}
}