【数据结构 最小堆】

父节点比他的左右子树的值都要小。下面给出了两个方法:

  1. 在最小堆中添加了一个元素后,经过上浮来重新构造最小堆
  2. 将一个完全无序的二叉树构造成最小堆,下沉。
package main.java.heap;

import java.util.Arrays;

/**
 * 构造最小堆
 *
 * @author Kimizu
 * @describe
 * @create 2022/3/25 11:54
 */
public class MinHeap {

    /**
     * 上浮,适合插入元素后调整
     *
     * @param heap 待调整的堆
     */
    public static void upAdjust(int[] heap) {
        int childIndex = heap.length - 1;
        // 无论是左子结点还是右子结点都能获取到父结点
        int parentIndex = (childIndex - 1) / 2;
        // temp保存插入的叶子节点值,用于最后赋值
        int temp = heap[childIndex];
        while (childIndex > 0 && temp < heap[parentIndex]) {
            // 插入的元素不满足最小堆
            heap[childIndex] = heap[parentIndex];
            // 父子指针上移
            childIndex = parentIndex;
            parentIndex = (parentIndex - 1) / 2;
        }
        heap[childIndex] = temp;
    }


    /**
     * 下沉,适合构造一个完全无序的堆
     *
     * @param heap        待调整的堆
     * @param parentIndex 要下沉的父节点
     * @param length      堆的有效大小
     */
    public static void downAdjust(int[] heap, int parentIndex, int length) {
        // temp保存父结点的值,用于最后赋值
        int temp = heap[parentIndex];
        // 先得到左节点
        int childIndex = 2 * parentIndex + 1;
        while (childIndex < length) {
            // 判断是否有右孩子,且右孩子的值小于左孩子,如果有,则定位到右孩子
            if (childIndex + 1 < length && heap[childIndex + 1] < heap[childIndex]) {
                childIndex++;
            }
            // 父结点值小于(左右)结点,满足最小堆
            if (temp <= heap[childIndex]) {
                break;
            }
            // 不满足
            heap[parentIndex] = heap[childIndex];
            parentIndex = childIndex;
            childIndex = 2 * childIndex + 1;
        }
        heap[parentIndex] = temp;
    }


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


    public static void main(String[] args) {
        /**
         * 构造前
         *                       1
         *             3                2
         *       6        5       7      8
         *   9    10  0
         *
         */

        /**
         * 构造后
         *                       0
         *             1                2
         *       6        3      7      8
         *   9    10  5
         *
         */
        int[] heap = {1, 3, 2, 6, 5, 7, 8, 9, 10, 0};
        upAdjust(heap);
        // [0, 1, 2, 6, 3, 7, 8, 9, 10, 5]
        System.out.println(Arrays.toString(heap));

        System.out.println("******************************");

        // 把一个无序数组构造成堆
        /**
         * 构造前
         *                       7
         *             1               3
         *       10        5       2      8
         *   9      6
         *
         */
        int[] heapNoOrder = {7, 1, 3, 10, 5, 2, 8, 9, 6};
        buildHeap(heapNoOrder);
        // [1, 5, 2, 6, 7, 3, 8, 9, 10]
        System.out.println(Arrays.toString(heapNoOrder));

        /**
         * 构造后
         *                         1
         *               5              2
         *         6        7       3      8
         *     9     10
         *
         */


    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值