Java实现堆算法的使用示例
作者:小筱在线
堆是一种特殊的数据结构,它是一棵完全二叉树,且满足堆的性质:对于每个节点,它的值都不小于(或不大于)它的孩子节点的值。根节点的值就是堆中的最大值(或最小值)。
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 堆算法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!