二叉堆及其基本操作

二叉堆

最大堆

最大堆的任何一个父节点的值,都大于或等于它
左、右孩子节点的值。
在这里插入图片描述

最小堆

最小堆的任何一个父节点的值,都小于或等于它
左、右孩子节点的值。
在这里插入图片描述

二叉堆的自我调整

插入节点

插入位置是完全二叉树的最后一个位置。然后慢慢上浮合适的位置,直到满足根节点都比孩子节点都小即可。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

删除节点

删除的是处于堆顶的节点。
在这里插入图片描述
把堆的最后一个节点10临时补到原本堆顶的位置。
在这里插入图片描述
节点10和它的左、右孩子进行比较,和最小的一个交换即可。

在这里插入图片描述
在这里插入图片描述

构建二叉堆

把一个无序的完全二叉树调整为二叉堆,本质就是让所有非叶子节点依次“下沉”。
找到比当前节点最小的一个孩子节点交换。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
堆的插入操作是单一节点的“上浮”,堆的删除操作是单一节点的“下沉”,这两个操作的平均交换次数都是
堆高度的一半,所以时间复杂度是O(logn)。
构建堆的时间复杂度是O(n)。

二叉堆的存储格式(采用数组进行层序遍历存储)

在这里插入图片描述
假设父节点的下标是parent,那么它的左孩子下标就是
2×parent+1;右孩子下标就是2×parent+2。

    /**
     * 上浮调整
     * @param array     待调整的堆
     */
    public static void upAdjust(int[] array) {
        int childIndex = array.length-1;
        int parentIndex = (childIndex-1)/2;
        // temp保存插入的叶子节点值,用于最后的赋值
        int temp = array[childIndex];
        while (childIndex > 0 && temp < array[parentIndex])
        {
            //无需真正交换,单向赋值即可
            array[childIndex] = array[parentIndex];
            childIndex = parentIndex;
            //这儿有大事情:如果当前节点的处于右孩子,则减1,还剩下1,
            //不能整除2,而除2之后会把多余的1给磨掉;
            //如果当前节点的处于左孩子,减1之后正好,可以够整除。
            parentIndex = (parentIndex-1) / 2;
            
        }
        array[childIndex] = temp;
    }

    /**
     * 下沉调整
     * @param array     待调整的堆
     * @param parentIndex    要下沉的父节点
     * @param length    堆的有效大小
     */
    public static void downAdjust(int[] array, int parentIndex, int length) {
        // temp保存父节点值,用于最后的赋值
        int temp = array[parentIndex];
        int childIndex = 2 * parentIndex + 1;
        while (childIndex < length) {
            // 如果有右孩子,且右孩子小于左孩子的值,则定位到右孩子
            //找到最小的那一个孩子
            if (childIndex + 1 < length && array[childIndex + 1] < array[childIndex]) {
                childIndex++;
            }
            // 如果父节点小于任何一个孩子的值,直接跳出
            if (temp <= array[childIndex])
                break;
            //无需真正交换,单向赋值即可
            array[parentIndex] = array[childIndex];
            parentIndex = childIndex;
            childIndex = 2 * childIndex + 1;
        }
        array[parentIndex] = temp;
    }

    /**
     * 构建堆
     * @param array     待调整的堆
     */
    public static void buildHeap(int[] array) {
        // 从最后一个非叶子节点开始,依次下沉调整
        for (int i = (array.length-2)/2; i >= 0; i--) {
            downAdjust(array, i, array.length);
        }
    }

    public static void main(String[] args) {
        int[] array = new int[] {1,3,2,6,5,7,8,9,10,0};
        upAdjust(array);
        System.out.println(Arrays.toString(array));

        array = new int[] {7,1,3,10,5,2,8,9,6};
        buildHeap(array);
        System.out.println(Arrays.toString(array));
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值