堆
堆:优先队列——取出元素的顺序依照元素的优先权(关键字)大小
堆的两种特性
·结构性:用数组表示的完全二叉树
·有序性:任意结点的关键字是其子树所有结点的最大(小)值
最大堆的操作
最大堆的定义
typedef struct HeapStruct *MaxHeap;
struct HeapStruct {
ElementType *Elements;//存储堆元素的数组
int size;//数组当前元素个数
int Capacity;//堆的最大容量
};
最大堆的创建
MaxHeap Create ( int MaxSize ) {
MaxHeap H = malloc( sizeof( struct HeapStruct ) );
H->Elements = malloc( sizeof( (MaxSize+1) * sizeof(ElementType)));
H->size = 0;
H->Capacity = MaxSize;
H->Elements[0] = MaxData;//定义“哨兵”为大于堆中所有可能元素的值,便于以后操作
return H;
}
最大堆的插入
void Insert ( MaxHeap H, ElemetType item ) {
int i;
if( IsFull(H) ) {
printf("最大堆已满");
return;
}
i = ++H->size;//i指向插入后堆中的最后一个元素的位置
//Elements[0]是“哨兵”元素,控制循环的结束
for( ;H->Elements[i/2]<item; i/=2 )
H->Elements[i] = H->Elements[i/2];//向下过滤结点
H->Elements[i] = item;//将item插入
}
最大堆的删除
ElementType DeleteMax( MaxHeap H ) { /* 从最大堆H中取出键值为最大的元素,并删除一个结点 */
int Parent, Child;
ElementType MaxItem, temp;
if ( IsEmpty(H) ) {
printf("最大堆已为空");
return ERROR;
}
MaxItem = H->Elements[1]; /* 取出根结点存放的最大值 */
/* 用最大堆中最后一个元素从根结点开始向上过滤下层结点 */
temp = H->Elements[H->Size--]; /* 注意当前堆的规模要减小 */
for( Parent=1; Parent*2<=H->Size; Parent=Child ) {
Child = Parent * 2;
if( (Child!=H->Size) //判别有无右儿子
&& (H->Elements[Child]<H->Elements[Child+1]) )
Child++; /* Child指向左右子结点的较大者 */
if( temp >= H->Elements[Child] ) break; /* 找到了合适位置 */
else /* 下滤temp */
H->Elements[Parent] = H->Elements[Child];
}
H->Elements[Parent] = X;
return MaxItem;
}
最大堆的建立
//建造最大堆
void PercDown( MaxHeap H, int p ) { /* 下滤:将H中以H->Data[p]为根的子堆调整为最大堆 */
int Parent, Child;
ElementType 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 /* 下滤X */
H->Data[Parent] = H->Data[Child];
}
H->Data[Parent] = X;
}
void BuildHeap( MaxHeap H )
{ /* 调整H->Data[]中的元素,使满足最大堆的有序性 */
/* 这里假设所有H->Size个元素已经存在H->Data[]中 */
int i;
/* 从最后一个结点的父节点开始,到根结点1 */
for( i = H->Size/2; i>0; i-- )
PercDown( H, i );
}