本文共 2921 字,大约阅读时间需要 9 分钟。
二叉堆
堆有两个性质:结构性和堆序行,必须满足这两个性质 结构性质:堆是一棵完全填满的二叉树。完全二叉树很有规律,可以用一个数组来实现,不需要用指针 1.对数组中任一位置i上的元素,其左儿子在2i,其右儿子在2i+1的位置,它的父亲在i/2上 堆序性质:使操作被快速执行的性质使堆序性。 1.对于最小堆(最小的关键字在根上),在一个堆中,对于每一个节点X,X的父亲的关键字应小于等于X的关建字,根节点除外 2.对于最大堆(最大的关键字在根上),在一个堆中,对于每一个节点X,X的父亲的关键字应大于等于X的关键字,根节点除外堆的基本操作(最小堆)
1.findMin(),找到最小元,只需要常数时间,最小元总是在根上 2.insert(),插入一个数到堆中 插入过程:在下一个位置创建一个空穴,插入到该位置,若不改变堆性质,则插入成功,否则,与父亲节点交换,直到满足堆的性质 这种策略叫做上滤。新元素在堆中直到找到正确的位置 3.deleteMin(),删除最小元 删除过程:把堆中的最后一个元素X,放入根节点,若不满足堆的性质,从它的子节点中找到最小的节点,交换位置,直到满足堆的性质 这种策略叫做下滤。堆结构和声明的函数
#define MinDate -9999struct HeapStruct;typedef struct HeapStruct *PriorityQueue;struct HeapStruct { int Capacity; //堆的容量大小 int Size; //当前堆中数据的个数 int *Elements; //存放元素};//函数声明PriorityQueue Initialize(int MaxElements); //初始化堆void Destroy(PriorityQueue H); //销毁堆void MakeEmpty(PriorityQueue H); //清空堆void Insert(int X, PriorityQueue H); //插入数据到堆int DeleteMin(PriorityQueue H); //删除最小堆中根节点int FindMin(PriorityQueue H); //找到最小的数据int IsEmpty(PriorityQueue H); //判断是否为空int IsFull(PriorityQueue H); //判断是否满
初始化函数
PriorityQueue Initialize(int MaxElements){ //初始化堆 PriorityQueue H; if (MaxElements < 10) { printf("堆太小了\n"); return NULL; } H = (struct HeapStruct*)malloc(sizeof(struct HeapStruct)); if (H == NULL) { printf("初始化失败\n"); return NULL; } H->Elements = (int*)malloc(sizeof(int)*(MaxElements + 1)); if (H->Elements == NULL) { printf("初始化失败\n"); } H->Capacity = MaxElements; H->Size = 0; H->Elements[0] = MinDate; //将第一个节点设为最小值,作为一个哨兵节点 return H;}
销毁堆函数和重置堆函数
void Destroy(PriorityQueue H) { //销毁堆,释放申请的空间 if (H != NULL) { if (H->Elements != NULL) { free(H->Elements); } free(H); }}void MakeEmpty(PriorityQueue H) { //清空堆中的数据 if (H!=NULL) { H->Size = 0; }}
判断堆空和堆满的函数,返回最小值的函数
int IsEmpty(PriorityQueue H) { //判断是否为空 if (H->Size == 0) { return 1; } return 0;}int IsFull(PriorityQueue H) { //判断是否已满 if (H->Size == H->Capacity) { return 1; } return 0;}int FindMin(PriorityQueue H) { //找到最小的数据 return H->Elements[1];}
插入数据函数
void Insert(int X,PriorityQueue H) { //插入数据 int i; if (IsFull(H)) { printf("堆中元素已满\n"); return; } for (i = ++H->Size; H->Elements[i / 2] > X; i /= 2) { //循环进行上滤操作 H->Elements[i] = H->Elements[i / 2]; } H->Elements[i] = X; //找到位置,成功插入}
弹出最小值并调整堆结构函数
int DeleteMin(PriorityQueue H) { //弹出最小的元素,调整最小堆 int i, child; int MinElement, LastElement; if (IsEmpty(H)) { printf("堆为空\n"); return H->Elements[0]; } MinElement = H->Elements[1]; LastElement = H->Elements[H->Size--]; for (i = 1; i * 2 <= H->Size;i = child) { //寻找最小的孩子 child = i * 2; if (child !=H->Size &&H->Elements[child] > H->Elements[child + 1]) { child++; } //判断,如果最小的孩子比最后位置的数小,那么删除空的位置由子节点代替,空格下滤 if (LastElement > H->Elements[child]) { H->Elements[i] = H->Elements[child]; } //若最小的孩子比最后位置的数大,删除空的位置由最后位置的数代替,下滤完成,跳出循环 else { break; } } H->Elements[i] = LastElement; return MinElement;}
转载地址:http://jmyo.baihongyu.com/