Java实现堆算法的使用示例

 更新时间:2023年12月13日 10:42:29   作者:小筱在线  
本文主要介绍了Java实现堆算法的使用示例,Java中提供了一个Heap类,可以用来实现堆的操作,可以实现如插入、删除、获取最大最小值等,具有一定的参考价值,感兴趣的可以了解一下

堆是一种特殊的数据结构,它是一棵完全二叉树,且满足堆的性质:对于每个节点,它的值都不小于(或不大于)它的孩子节点的值。根节点的值就是堆中的最大值(或最小值)。

Java中提供了一个Heap类,可以用来实现堆的操作。Heap类是一个抽象类,它定义了堆的基本操作方法,如插入、删除、获取最大(或最小)值等。

要使用Heap类,需要创建一个具体的实现类,例如MaxHeap和MinHeap。这些类继承自Heap类,并实现了具体的插入、删除、获取最大(或最小)值等方法。下面我们以MaxHeap为例,来详细介绍如何实现堆。

MaxHeap的实现思路如下:

  • 定义一个数组来保存堆的元素,数组下标从1开始。

  • 定义一个变量来记录堆中元素的数量。

  • 实现插入方法:新元素插入到数组最后,然后使用上滤操作将新元素沿着路径向上移动,直到堆的性质被满足。

  • 实现删除方法:移除堆顶元素(数组下标为1的元素),然后将数组最后一个元素替换到堆顶,使用下滤操作将新元素沿着路径向下移动,直到堆的性质被满足。

  • 实现获取最大值方法:直接返回堆顶元素。

  • 实现堆排序方法:依次取出堆顶元素,将其放到一个新的数组中,然后重新调整堆。

以下是MaxHeap的代码实现:

public class MaxHeap<T extends Comparable<T>> {
    private T[] heap; // 堆元素数组
    private int size; // 堆元素数量

    @SuppressWarnings("unchecked")
    public MaxHeap(int capacity) {
        heap = (T[]) new Comparable[capacity + 1]; // 数组下标从1开始
        size = 0;
    }

    public void insert(T value) {
        if (size == heap.length - 1) {
            resize();
        }

        heap[++size] = value; // 新元素插入到数组最后
        swim(size); // 上滤操作
    }

    public T deleteMax() {
        if (size == 0) {
            throw new NoSuchElementException();
        }

        T max = heap[1]; // 堆顶元素
        heap[1] = heap[size--]; // 将数组最后一个元素替换到堆顶
        sink(1); // 下滤操作
        heap[size + 1] = null; // 释放旧的堆顶元素

        return max;
    }

    public T getMax() {
        if (size == 0) {
            throw new NoSuchElementException();
        }

        return heap[1];
    }

    public void heapSort(T[] arr) {
        heapify(arr); // 初始化堆
        for (int i = size; i > 0; i--) {
            arr[i - 1] = deleteMax(); // 依次取出堆顶元素
        }
    }

    private void swim(int k) {
        while (k > 1 && heap[k].compareTo(heap[k / 2]) > 0) { // 父节点小于当前节点,上滤
            swap(k, k / 2);
            k /= 2; // 移动到父节点
        }
    }

    private void sink(int k) {
        while (2 * k <= size) { // 如果有左孩子
            int j = 2 * k;
            if (j < size && heap[j].compareTo(heap[j + 1]) < 0) { // 选择左右孩子中较大的那个
                j++;
            }

            if (heap[k].compareTo(heap[j]) >= 0) { // 如果父节点不小于孩子节点,下滤结束
                break;
            }

            swap(k, j); // 父节点和子节点交换
            k = j; // 移动到子节点
        }
    }

    private void heapify(T[] arr) {
        heap = (T[]) new Comparable[arr.length + 1];
        size = arr.length;

        System.arraycopy(arr, 0, heap, 1, arr.length); // 复制数组元素到堆中

        for (int i = size / 2; i >= 1; i--) { // 倒序下滤,从最后一个非叶子节点开始
            sink(i); // 下滤操作
        }
    }

    private void resize() {
        int newSize = heap.length * 2;
        heap = Arrays.copyOf(heap, newSize);
    }

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

上面的代码实现了MaxHeap类,它支持插入、删除、获取最大值和堆排序等操作。堆排序的实现就是先将数组元素初始化成一个堆,然后依次取出堆顶元素,进行排序。

MaxHeap类中使用了泛型,可以存储任意类型的元素,只要实现了Comparable接口。使用时,可以像下面这样创建一个MaxHeap对象,然后调用其方法进行操作:

MaxHeap<Integer> maxHeap = new MaxHeap<>(10);
maxHeap.insert(3);
maxHeap.insert(1);
maxHeap.insert(4);
maxHeap.insert(1);
maxHeap.insert(5);
System.out.println(maxHeap.deleteMax()); // 输出:5
System.out.println(maxHeap.getMax()); // 输出:4

Integer[] arr = {3, 1, 4, 1, 5};
maxHeap.heapSort(arr);
System.out.println(Arrays.toString(arr)); // 输出:[1, 1, 3, 4, 5]

总的来说,实现堆的关键在于实现上滤和下滤操作。上滤操作用于插入新元素时,将其从叶子节点沿着路径向上移动,下滤操作用于删除堆顶元素时,将最后一个元素从根节点沿着路径向下移动,维护堆的性质。堆排序的实现就是先将数组初始化成一个堆,然后依次取出堆顶元素,进行排序。最后,需要注意的是,在Java中实现堆可以使用Heap类,但也可以自己实现一个堆类,可以根据具体需求进行设计和优化。

到此这篇关于Java实现堆算法的使用示例的文章就介绍到这了,更多相关Java 堆算法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java连接zookeeper的3种方式小结

    java连接zookeeper的3种方式小结

    这篇文章主要介绍了java连接zookeeper的3种方式小结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • Springboot实现多文件上传代码解析

    Springboot实现多文件上传代码解析

    这篇文章主要介绍了Springboot实现多文件上传代码解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • springboot配置允许循环依赖问题

    springboot配置允许循环依赖问题

    这篇文章主要介绍了springboot配置允许循环依赖问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • Java代码优化细节

    Java代码优化细节

    这篇文章主要为大家详细介绍了Java代码优化细节,通过不同细节对java代码进行优化,感兴趣的小伙伴们可以参考一下
    2016-08-08
  • 浅谈Java成员变量与属性的区别(简单最易懂的解释)

    浅谈Java成员变量与属性的区别(简单最易懂的解释)

    下面小编就为大家带来一篇浅谈Java成员变量与属性的区别(简单最易懂的解释)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • 关于Spring Actuator的简单测试

    关于Spring Actuator的简单测试

    这篇文章主要介绍了关于Spring Actuator的简单测试,Spring-Actuator 是spring下的程序监控系统,通过简单的配置就可以查看程序的相关信息,本文提供了相关配置,需要的朋友可以参考下
    2023-10-10
  • EL表达式的隐式对象_动力节点Java学院整理

    EL表达式的隐式对象_动力节点Java学院整理

    这篇文章主要介绍了EL表达式的隐式对象,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • Java转换解析中间带有 “T“和“Z“ 的时间格式

    Java转换解析中间带有 “T“和“Z“ 的时间格式

    这篇文章主要给大家介绍了关于Java转换解析中间带有 “T“和“Z“ 的时间格式,相信很多小伙伴在时间格式转换的时候非常头疼,文中通过代码示例介绍的非常详细,需要的朋友可以参考下
    2024-01-01
  • Mybatis防止sql注入原理分析

    Mybatis防止sql注入原理分析

    这篇文章主要介绍了Mybatis防止sql注入原理分析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • java读取文件内容,解析Json格式数据方式

    java读取文件内容,解析Json格式数据方式

    这篇文章主要介绍了java读取文件内容,解析Json格式数据方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09

最新评论