堆的向下调整

堆(heap)的概念

  1. 逻辑上是一颗完全二叉树;
  2. 物理上保存在数组中;
  3. 满足任意结点的值都大于其子树中结点的值称为大堆/大根堆/最大堆;
  4. 反之则为小堆/小根堆/最小堆;
  5. 堆的作用:快速找集合中最大值。

堆的向下调整

前提:
左右子树已经是一个堆,才能调整

说明:

  • array 代表存储堆的数组
  • size 代表数组中被视为堆数据的个数
  • index 代表要调整位置的下标
  • left 代表 index 左孩子下标
  • right 代表 index 右孩子下标
  • min 代表 index 的最小值孩子的下标

操作过程(以小堆为例):

  1. index如果已经是叶子结点,则整个调整过程结束;
    (1) 判断index位置有没有孩子;
    (2)因为堆是完全二叉树,没有左孩子就一定没有右孩子,所以判断是否有左孩子;
    (3)因为对的存储结构是数组,所以判断是否有左孩子即判断左孩子下标是否越界,即left>=size越界。
  2. 确定left或right,谁是index的最小孩子min;
    (1)如果右孩子不存在,则min=left;
    (2)否则,比较array[left]和array[right]值的大小,选择小的为min。
  3. 比较array[index]的值和array[min]的值,如果array[index]<=array[min],则满足堆的性质,调整结束;
  4. 否则,交换 array[index] 和 array[min] 的值;
  5. 然后因为 min 位置的堆的性质可能被破坏,所以把 min 视作 index,向下重复以上过程。
    时间复杂度分析:
    最坏的情况即图示的情况,从根一路比较到叶子,比较的次数为完全二叉树的高度即时间复杂度为 O(log(n))。
    图示:在这里插入图片描述

代码:

import java.util.*;
public class Heap {
    public static void shiftDownSmall(int[] array,int size,int index){
        //向下调整(小堆)
        int left=2*index+1;
        while(left<size) {
            int right = left + 1;
            int min = left;
            if (right < size&&array[right] < array[left]){
                min = right;
            }
            if(array[index]>array[min]){
                swap(array,index,min);
                index=min;
                left=2*index+1;
            }else{
                break;
            }
        }
    }
    public static void shiftDownBig(int[] array,int size,int index){
        //向下调整(大堆)
        while (2 * index + 1 < size) {
            int m = 2 * index + 1;
            if (m + 1 < size && array[m + 1] > array[m]) {
                m++;
            }
            if (array[index] >= array[m]) {
                break;
            }
            swap(array, index, m);
            index = m;
        }
    }
    private static void swap(int[] array, int i, int j) {
        int t=array[i];
        array[i]=array[j];
        array[j]=t;
    }
    public static void main(String[] args) {
        int[] small={27,15,19,18,28,34,65,49,25,37};
        shiftDownSmall(small,small.length,0);
        System.out.println(Arrays.toString(small));
        int[] big = { 100, 10, 88, 25, 40, 80, 70,18};
        shiftDownBig(big, big.length, 1);
        System.out.println(Arrays.toString(big));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值