堆的定义:
堆通常是一个可以被看做一棵完全二叉树的数组对象。二叉堆满足如下性质: 堆中某个节点的值总是不大于或不小于其父节点的值;
堆总是一棵完全二叉树。 将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。
堆的存储:
#define Elementtype int
typedef struct MaxHeap{
Elementtype *Elements;
int Capacity;//堆的大小
int size;//当前堆元素的个数
}MaxHeap;
完全二叉树的节点父子关系:
(1)非根节点,序号(i >1)父节点的序号为i/2;
(2)节点的序号为i,左孩子的序号为2 * i;
(3)节点的序号为i,右孩子的序号为2 * i + 1;
最大堆的插入操作:
算法思想:
先将值插在堆的最后(既数组的最后) 然后向上调整。怎么调整呢? 因为是最大堆,所以如果该节点的值 大于父节点的值 就交换他与父节点的值。循环操作。直到父节点的值大于该节点。
void MaxHeap_insert(MaxHeap* H , Elementtype data){
//将值插在堆的最后(既数组的最后) 然后向上调整
if(Is_Full(H)){
printf("最大堆已满");
return;
}
H ->Elements[(H ->size)++] = data;//放在数组的最后 并且size++
int child = (H ->size) - 1;//新插入的元素下标 赋予 child
int parent = ( child - 1 ) / 2;//新插入元素的父节点 下标赋予 parent
//向上调整
while(parent > 0){
if(H ->Elements[parent] < H ->Elements[child]){
int tem = H ->Elements[child];
H ->Elements[child] = H ->Elements[parent];
H ->Elements[parent] = tem;
child = parent;
parent = (parent - 1) % 2;
}else{
break;
}
}
}
最大堆的删除操作:
算法思想:
将Element[size - 1] 赋予 Element[0].并且size减一。然后将Element[0]既现在的根节点,向下调整.
找出根节点的 左右孩子较大的节点 。假设是右节点,如果根节点的值小于 右节点的值,则交换它俩的值。然后以右节点为根节点循环上述操作。直到根节点的值大于左右节点为止。(要注意左右孩子为空的情况)
//向下调整 条件左右子树都是最大堆 经过一次向下调整 该数变成最大堆;
void D_adjust(Elementtype* arr , int numsize, int parent){
//传入数组首地址 arr 数组大小 numsize。下调的位置parent
int child = 2 * parent +1;
while(child < numsize){
if(child + 1 < numsize && arr[child] < arr[child + 1]){
child = child +1;
}
if(arr[parent] < arr[child]){
int tem = arr[child];
arr[child] = arr[parent];
arr[parent] = tem;
parent = child;
child = child * 2 + 1;
}else{
break;
}
}
}
void MaxHeap_Delete(MaxHeap* H){
if(Is_Empty(H)){
printf("堆已空");
return ;
}
H ->Elements[0] = H ->Elements[ --(H ->size) ];//左右子树都是最大堆
D_adjust(H ->Elements,H ->size,0);
}
建堆操作:
要求:
给一个数组,按照数组跟树的关系,构成的完全二叉树不是最大堆,将它调整成最大堆。
算法思路:
假如一个堆不是最大堆,但它的左子树,右子树都是最大堆。那么我们用一次向下调整就可以将它变成最大堆。但对于一个乱序的数组它的左右子树不一定是最大堆。那么我们可以从该树的最后一个叶子节点的父节点开始按照数组下标减少的方向,依次做向下调整,直到根节点做完最后一次向下调整后算法结束,形成的新的二叉树为最大堆。
MaxHeap* MaxHeap_Creat(int MaxSize , Elementtype* arr,int Size){
MaxHeap* H = (MaxHeap*)malloc(sizeof(MaxHeap));
H ->Capacity = MaxSize;
H ->Elements = (Elementtype*)malloc(sizeof(Elementtype) * (H ->Capacity + 1));
H ->size = 0;
int child = Size - 1;
int parent = (child - 1)/2;
while(parent >= 0){
D_adjust(arr , Size, parent);//向下调整
parent--;
}
for(int i = 0;(i < Size && i < MaxSize);i++){
H ->Elements[i] = arr[i];
H ->size ++;
}
return H;
}