最大堆特点 :
1.每个节点最多有俩个节点
2.根节点的键值是所有堆节点键值中最大者,且灭个节点值都比其孩子的值打.
3.除了根节点没有兄弟节点,最后一和左子节点可以没有兄弟节点,其他节点必须有兄弟节点
i的子节点左: 2i+1 i的右子节点:2i+2
i的父节点:(i-1)/2
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DEFAULT_CAPCITY 128 //堆的最大容量
typedef struct _Heap{
int *arr; //存储堆元素的数组,直接指向数组的地址
int size; //当前已存储的元素个数
int capacity; //当前存储的容量
}Heap;
bool initHeap(Heap &heap,int *orginal,int size);
static void buildHeap(Heap &heap);
static void adjustDown(Heap &heap,int index);
//初始化堆
bool initHeap(Heap &heap,int *orginal,int size){
int capacity = DEFAULT_CAPCITY>size ? DEFAULT_CAPCITY:size;
heap.arr = new int[capacity];
if(!heap.arr) return false;
heap.capacity = capacity;
heap.size = 0;
//如果存在原始数据结构则构建堆
if(size>0){
memcpy(heap.arr,orginal,size*sizeof(int));
heap.size = size;
buildHeap(heap);
}else{
heap.size = 0;
}
return true;
}
/*从最后一个父节点(size/2-1)的位置逐个往前调整所有的父节点直到根节点,
确保每一个父节点都是一个最大堆,最后整体上形成一个最大堆
*/
void buildHeap(Heap &heap){
int i;
for(i=heap.size /2-1;i>=0;i--){
adjustDown(heap,i);
}
}
//将当前的节点和子节点调整成最大堆
void adjustDown(Heap &heap,int index){
int cur = heap.arr[index];//当前待调整的节点
int parent,child;
/*判断是否存在大于当前节点的子节点,如果不存在,则堆本身是平衡的
不需要调整,如果存在,则将最大的子节点与之交换,
交换后,如果子节点还有子节点,则继续按照同样的步骤堆这个子节点进行调整*/
for(parent=index;(parent*2+1)<heap.size;parent=child){
child=parent*2+1;
//取俩个子节点中最大的节点
if(child+1<heap.size && heap.arr[child]<heap.arr[child+1]){
child++;
}
//判断最大的子节点是否大于当前的父节点
if(cur>=heap.arr[child]){//不大于,则不需要调整
break;
}else{//大于当前的父节点,进行交换,然后从子节点位置继续向下调
heap.arr[parent] = heap.arr[child];
heap.arr[child] = cur;
}
}
}
int main(){
Heap hp;
int origVals[]={1,2,3,87,93,82,92,86,95};
int i = 0;
if(!initHeap(hp,origVals,sizeof(origVals)/sizeof(origVals[0]))){
fprintf(stderr,"初始化堆失败!\n");
}
for(i = 0;i<hp.size;i++){
printf("the %dth element:%d\n",i,hp.arr[i]);
}
system("pause");
return 0;
}