堆 03 提取 & 下沉

E extractMax() - 提取堆中最大的元素

  • 堆中最大的元素:
    • 堆中最大的元素就是堆顶的元素;
    • 从二叉树的角度看,堆中最大的元素就是二叉树的根节点;
    • 从数组的角度看,堆中最大的元素就是数组中索引为0的元素;
  • 提取堆中最大的元素:
    • 找到堆中最大的元素并返回很简单,但提取涉及到要把最大的元素从堆中删除(即逻辑上删除二叉树的根,物理上删除数组索引为0的元素),就要重组剩余元素的结构,使之仍然能够满足堆的定义;
    • 具体删除最大堆中的堆顶元素的做法如下:
      • 让堆顶元素和堆中最后一个元素互换位置;
      • 删除堆中最后一个元素,即刚换过来的原堆顶元素;
      • 下沉新堆顶元素,使整个二叉树重新满足堆的定义;
// 看堆中的最大元素
public E findMax(){
    if(data.getSize() == 0)
        throw new IllegalArgumentException("Can not findMax when heap is empty.");
    return data.get(0);
}

// 取出堆中最大元素
public E extractMax(){
    E ret = findMax();

    data.swap(0, data.getSize() - 1);
    data.removeLast();
    siftDown(0);

    return ret;
}

void siftDown(int k) - 下沉新的堆顶元素

  • 下沉的终止条件,即k指向的元素已经没有可下沉的空间了,这个状态为:k的左孩子的索引已经大于等于size,size从索引的角度看,指向下一个码元素的位置;当堆中只有一个元素,size==1,size指向堆顶元素的左孩子,堆顶元素左孩子的索引也是1,下一个堆中元素的码放位置是堆顶元素左孩子的位置,说明堆顶元素没有左孩子,更没有右孩子,这就是k没有下沉空间的状态了,k但凡还有个左孩子(就是有孩子,k还没到最底层),它就还有下沉的空间
  • 用一个指针j指向k的左孩子;
  • 看 k 是否还有右孩子,并且 k 的右孩子比 k 的左孩子大,那么让 j 指向 k 的右孩子,否则 j 还指向 k 的左孩子,此时 j 指向 k 的疑似下沉位置
  • k 和其疑似下沉位置做比较,如果 k 不比其疑似下沉位置的元素小,则不需要下沉,跳出循环,下沉动作结束;
  • 如果 k 比其疑似下沉位置的元素小,开始下沉动作,交换 k 和其疑似下沉位置的元素;
  • 下沉完成以后,让 k 重新追上待下沉元素;
private void siftDown(int k){
    while(leftChild(k) < data.getSize()){
        int j = leftChild(k); 
        // 如果k有右孩子,并且右孩子比左孩子大
        if( j + 1 < data.getSize() &&
                data.get(j + 1).compareTo(data.get(j)) > 0 )
            j ++;   // j 指向 leftChild 和 rightChild 中更大的那一个
    
        // 如果不需要下沉,跳出循环,下沉动作结束
        if(data.get(k).compareTo(data.get(j)) >= 0 )
            break;
        
        // k 和 j 交换位置,待下沉元素和左右孩子中更大的那个交换位置
        data.swap(k, j);
        // k 重新追上待下沉的元素
        k = j;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值