目录
堆的删除(最大堆)
思路
代码
解析
堆的删除(最大堆)
思路
代码
ElementType DeleteMax( MaxHeap H )
{ /* 从最大堆H中取出键值为最大的元素,并删除一个结点 */
int Parent, Child;
ElementType MaxItem, X;
if ( IsEmpty(H) )
{
printf("最大堆已为空");
return ERROR;
}
MaxItem = H->Data[1]; /* 取出根结点存放的最大值 */
/* 用最大堆中最后一个元素从根结点开始向上过滤下层结点 */
X = H->Data[H->Size--]; /* 注意当前堆的规模要减小 */
for( Parent=1; 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;
return MaxItem;
}
解析
判断最大堆是否为空,如果为空则返回错误。
取出根结点存放的最大值,即最大元素。 放在临时变量MaxItem中。
将堆的规模减一。
这里的变量parent,用于表示当前结点的父结点在最大堆中的下标位置。
在删除最大值的操作中,我们需要将最后一个元素放到根结点的位置,
然后从根结点开始向下过滤,找到合适的位置,使得最大堆的性质得以保持。
在向下过滤的过程中,我们需要比较当前结点和其左右子结点的大小关系,
如果当前结点比其子结点都大,那么就找到了合适的位置,可以结束操作。
否则,我们需要将当前结点和其子结点中较大的那个交换位置,然后继续向下过滤。
在这个过程中,parent变量的作用是表示当前结点的下标位置,方便我们进行比较和交换操作。
在最大堆中,每个结点的左子结点下标为2i,右子结点下标为2i+1,其中i为当前结点的下标。
当一个结点只有左子结点时,其右子结点下标为2i+1,超出了最大堆的范围,
因此需要判断 child != H->size,即该节点是否有右子节点,(child先指向的是左子结点,若child == H->size,就说明已经是堆中的最大值了,意味着没有右子结点了)
如果有,则需要比较左右子节点的大小,选择较大的子节点进行下滤操作。
如果没有右子节点,则直接将左子节点与X进行比较。
最后,将 X 插入到 Parent 的位置上即可。
函数结束,返回最大堆中键值最大的元素。
end
学习自:MOOC数据结构——陈越、何钦铭