最大堆的插入和删除

首先,我们要了解堆这种数据结构,这里的堆具有完全二叉树的结构,并且堆树中某个节点的值总是不大于或不小于其孩子节点的值(‘不大于’的情况叫最小堆,‘不小于的情况叫最大堆’),堆树中每个节点的子树都是堆树。
这里我们顺便科普一下完全二叉树,完全二叉树从根结点到倒数第二层满足完美二叉树,最后一层可以不完全填充,其叶子结点都靠左对齐。
如下图所示:
在这里插入图片描述
要实现堆的删除和插入需要明白一些逻辑:堆是用数组实现的二叉树,假设节点的索引值为index,那么:

节点的左子节点是 2index+1,
节点的右子节点是 2
index+2, 
节点的父节点是 (index-1)/2。

堆(最大堆)的插入:
首先将元素插入到堆的末尾的节点,然后依次和父几点比较,如果比父节点的值大,就将父节点向下过滤,以父节点的值下于插入节点的值为条件不断循环,最终找到合适的位置,进行插入。

堆(最大堆)的删除:
根节点即最大的节点,取出根节点后我们需要找到合适的节点代替,取出末尾的节点,让末尾节点与根节点的子节点比较,如果大于两个子节点中的任意一个,则顶替父节点,如果不满足条件,选择最值大的儿子充当根节点,,依次类推,总结一句就是儿子能上,就儿子上,儿子不能上位,就末尾节点上(不知这样表达是否准确)。

下面是实现方法的伪代码:

1.堆的创立:

   //最大堆的创建
   typedef struct HeapStruct *MaxHeap;
   struct HeapStruct{
   ElementType *Elements;/*存储堆元素的数组*/
   int size;/*堆的当前元素的个数*/
   int Capacity;/*堆的最大容量*/
   };
   MaxHeap Create(int MaxSize)
   { /*创建最大容量为MaxSize的空的堆栈*/
   MaxHeap H =malloc(sizeof(struct HeapStruct)};
   H->Elements=malloc((MaxSize+1)*sizeof(ElementType));
   H->Size=0;
   H->Capacity=MaxDate;
   /*定义“哨兵”为大于堆中的所有可能元素的值,便于以后更快操作*/
   return H;
   }

2.节点插入:

Void Insert(MaxHeap H,ElementType item)
{
int i;
if(isFull(H)){
printf("最大堆已满");
return ;
}
i=++H->Size;/*指向插入后堆中的最后一个元素的位置*/
for(; H->Elements[i/2]<item;i/=2)
 {
 H->Elements[i]=H->Elements[i/2];/*向下过滤节点*/
 }
 H->Elements[i]=item;/*将item插入*/
 }
  1. 删除最大值:
ElementType DeleteMax(MaxHeap H)
{/*从最大堆H里面取出键值为最大的元素,并删除一个节点*/
 int Parent,Child;
 ElementType MaxItem temp;
 if(IsEmpty (H)){
 printf("堆栈已经为空");
 return ;
 }
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]=H->Elements[Child];
   return MaxItem;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值