详解Java堆的应用场景,思路分析,代码实现

1.前言

堆作为一种数据结构,具有以下几个优点:

  1. 高效的插入和删除操作:堆的插入和删除操作的时间复杂度都是O(logn),其中n是堆中元素的个数。这是因为堆的结构保证了根节点是最大或最小元素,因此在插入或删除元素时只需要对部分节点进行调整,而不需要对所有节点进行遍历。这使得堆在动态维护一组元素中的最大或最小值时非常高效。

  2. 快速找到最大或最小元素:堆的结构保证了根节点是最大或最小元素,因此可以在常数时间内找到最大或最小元素。这对于需要频繁查找最大或最小值的应用非常有用,例如优先队列、任务调度等。

  3. 堆排序:堆排序是一种利用堆进行排序的算法,其时间复杂度为O(nlogn),并且具有原地排序的特点。堆排序不仅可以得到有序的结果,还可以同时支持升序和降序排序。

  4. 可以用于解决一些经典问题:堆可以用来解决一些经典的问题,例如求解Top K问题(查找前K大或前K小的元素)、求解中位数问题等。通过合理地利用堆的性质,可以高效地解决这些问题。

  5. 可以用于构建其他数据结构:堆可以作为其他数据结构的基础,例如图算法中的最小生成树算法(Prim算法、Dijkstra算法)、哈夫曼树等。通过将堆与其他数据结构相结合,可以得到更加高效的算法和数据结构。

综上所述,堆作为一种高效的数据结构,在插入、删除、查找最值等操作上具有显著的优势,并且可以应用于各种场景中,提供高效的解决方案。

2.思路分析 

当我们实现大顶堆的数据结构时,可以按照以下步骤进行思路分析:

  1. 首先,我们需要一个数组来存储堆的元素。在构造函数中,我们初始化堆的容量和元素个数,并创建一个具有指定容量的整型数组来表示堆。

  2. insert(int value) 方法用于向堆中插入一个元素。我们首先检查堆是否已满,如果已满则抛出异常。然后,将要插入的元素放在数组的末尾位置,然后调用 siftUp 方法将元素上移,以保持堆的性质。最后,增加堆的元素个数。

  3. extractMax() 方法用于从堆中取出最大值(即堆顶元素)。我们首先检查堆是否为空,如果为空则抛出异常。然后,将堆顶元素与数组末尾的元素交换位置,然后调用 siftDown 方法将新的堆顶元素下移,以保持堆的性质。最后,减少堆的元素个数,并返回之前的堆顶元素。

  4. siftUp(int index) 方法用于将指定位置的元素上移,直到满足堆的性质。我们使用一个循环来迭代执行以下操作:首先,计算父节点的索引(通过 (index - 1) / 2)。然后,检查当前元素是否大于其父节点的值。如果不是,则停止上移操作。否则,交换当前元素与父节点的位置,并更新当前元素的索引为父节点的索引。继续迭代直到满足堆的性质。

  5. siftDown(int index) 方法用于将指定位置的元素下移,直到满足堆的性质。我们使用一个循环来迭代执行以下操作:首先,计算左子节点和右子节点的索引(通过 2 * index + 12 * index + 2)。然后,找到当前节点、左子节点和右子节点中的最大值的索引。如果当前节点已经是最大值,则停止下移操作。否则,交换当前节点与最大值节点的位置,并更新当前节点的索引为最大值节点的索引。继续迭代直到满足堆的性质。

  6. swap(int i, int j) 方法用于交换数组中两个位置的元素。我们使用一个临时变量来保存一个位置的元素,然后将另一个位置的元素赋值给第一个位置,最后将临时变量的值赋给第二个位置。

通过以上步骤,我们可以实现一个基本的大顶堆数据结构,并进行插入和删除操作。这样的实现可以帮助我们在堆中快速找到最大值,并保持堆的性质。

3.代码实现 

package day14;
//大顶堆
public class MaxHeap {
    private int[] heap; // 存储堆元素的数组
    private int size; // 堆中元素的个数
    private int capacity; // 堆的容量

    public MaxHeap(int capacity) {
        this.capacity = capacity;
        this.size = 0;
        this.heap = new int[capacity];
    }

    public void insert(int value) {
        if (size >= capacity) {
            throw new IllegalStateException("Heap is full");
        }

        heap[size] = value; // 将元素放在数组末尾
        siftUp(size); // 上移元素
        size++; // 元素个数加1
    }

    public int extractMax() {
        if (size <= 0) {
            throw new IllegalStateException("Heap is empty");
        }

        int max = heap[0]; // 取出堆顶元素
        heap[0] = heap[size - 1]; // 将最后一个元素放到堆顶
        size--; // 元素个数减1
        siftDown(0); // 下移堆顶元素
        return max; // 返回堆顶元素
    }

    private void siftUp(int index) {
        while (index > 0) { // 如果不是根节点
            int parentIndex = (index - 1) / 2; // 计算父节点的索引
            if (heap[index] <= heap[parentIndex]) { // 如果不大于父节点
                break; // 停止上移
            }
            swap(index, parentIndex); // 交换元素
            index = parentIndex; // 更新索引
        }
    }

    private void siftDown(int index) {
        while (index < size) { // 如果不是叶子节点
            int leftChildIndex = 2 * index + 1; // 计算左子节点的索引
            int rightChildIndex = 2 * index + 2; // 计算右子节点的索引
            int largestIndex = index; // 假设当前节点最大

            if (leftChildIndex < size && heap[leftChildIndex] > heap[largestIndex]) { // 如果左子节点存在且大于当前节点
                largestIndex = leftChildIndex; // 更新最大值索引
            }
            if (rightChildIndex < size && heap[rightChildIndex] > heap[largestIndex]) { // 如果右子节点存在且大于当前节点
                largestIndex = rightChildIndex; // 更新最大值索引
            }

            if (largestIndex == index) { // 如果当前节点就是最大值
                break; // 停止下移
            }
            swap(index, largestIndex); // 交换元素
            index = largestIndex; // 更新索引
        }
    }

    private void swap(int i, int j) {
        int temp = heap[i];
        heap[i] = heap[j];
        heap[j] = temp;
    }
}

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风止￴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值