二叉堆满足其结构性,和堆序性。结构性:要求为完全二叉树,即除树的最底层外,树被完全填满,且底层的元素从左向右填充。堆序性:即在堆中要求,对任意元素X,X的父节点的关键字小等于X的关键字,如此得到最小堆。同理可得最大堆。 由于堆序性,因此二叉堆也常称为实现优先队列(Priority Queue)。
在对二叉堆进行操作时需要始终保持其结构性和堆序性。可用数组来实现二叉堆。数组中的元素关系为:i位置上的节点,其左儿子在2i上,右节点在2i+1上,父节点在i/2(取整)上。用数组代替树结构,从而不用包含指针操作。
具体实现代码如下:
Binary_Heap.h:
#ifndef _BINARY_HEAP_ #define __BINARY_HEAP_ class HeapStruct; typedef HeapStruct* Heap; typedef int ElementType; Heap Initialize(int MaxElement); void Distory(Heap H); void MakeEmpty(Heap H); void Insert(ElementType X,Heap H); ElementType DeleteMin(Heap H); ElementType FindMin(Heap H); int IsEmpty(Heap H); int IsFull(Heap H); struct HeapStruct { int Capacity; int Size; ElementType *Elements; }; int MinData=-1;//用于标记 #endif
Binary_Heap.c:
#include "Binary_Heap.h" #include <stdio.h> Heap Initialize(int MaxElement) { if (MaxElement<=0) return nullptr; Heap H=new HeapStruct; if(nullptr==H) { printf("out of Space \n"); return nullptr; } H->Elements=new ElementType[MaxElement+1];//第一个元素为MinData标记 if(nullptr==H->Elements) { printf("Out of Space \n"); return nullptr; } H->Capacity=MaxElement; H->Size=0; H->Elements[0]=MinData; return H; } void Distory( Heap H) { if(H->Elements!=nullptr) delete[] H->Elements; delete H; } void MakeEmpty(Heap H) { if(H->Elements!=nullptr) delete[] H->Elements; H->Elements=nullptr; H->Size=0; } int IsEmpty(Heap H) { if(0==H->Size) return 1; else return 0; } int IsFull(Heap H) { if(H->Size==H->Capacity) return 1; else return 0; } //在尾部插入新元素,并进行上滤操作,直到满足堆序性。 //注意:必满显示的交换赋值操作 void Insert(ElementType X,Heap H) { if(IsFull(H)) return; int i; for( i=++H->Size;H->Elements[i/2]>X;i/=2)//用MinData标记来防止i/2越界 H->Elements[i]=H->Elements[i/2]; H->Elements[i]=X;//避免显示交换的赋值 } //删除头部的最小元,并对空穴进行下滤操作,直到满足堆序性。 //注:如何避免显示的交换赋值操作 ElementType DeleteMin(Heap H) { if(IsEmpty(H)) return H->Elements[0]; int Child ,i; ElementType TempCell; ElementType MinElement=H->Elements[1]; ElementType 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; } ElementType FindMin(Heap H) { if(IsEmpty(H)) return H->Elements[0]; else return H->Elements[1]; }
//简单测试 void main() { Heap H=Initialize(20); int A[]={12,2,21,2,45,4,23,4,19,6,21,31,25,22}; for(int i=0;i<14;++i) Insert(A[i],H); for(int i=0;i<14;++i) A[i]=DeleteMin(H); for(int i=0;i<14;++i)//将得到的排序后的元素输出。这也正是堆排序的基本思想 printf("%d ",A[i]); }
原文:http://blog.csdn.net/yuyixinye/article/details/44560571