• Java实现堆算法


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

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

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

    MaxHeap的实现思路如下:

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

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

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

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

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

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

    以下是MaxHeap的代码实现:

    1. public class MaxHeapextends Comparable> {
    2. private T[] heap; // 堆元素数组
    3. private int size; // 堆元素数量
    4. @SuppressWarnings("unchecked")
    5. public MaxHeap(int capacity) {
    6. heap = (T[]) new Comparable[capacity + 1]; // 数组下标从1开始
    7. size = 0;
    8. }
    9. public void insert(T value) {
    10. if (size == heap.length - 1) {
    11. resize();
    12. }
    13. heap[++size] = value; // 新元素插入到数组最后
    14. swim(size); // 上滤操作
    15. }
    16. public T deleteMax() {
    17. if (size == 0) {
    18. throw new NoSuchElementException();
    19. }
    20. T max = heap[1]; // 堆顶元素
    21. heap[1] = heap[size--]; // 将数组最后一个元素替换到堆顶
    22. sink(1); // 下滤操作
    23. heap[size + 1] = null; // 释放旧的堆顶元素
    24. return max;
    25. }
    26. public T getMax() {
    27. if (size == 0) {
    28. throw new NoSuchElementException();
    29. }
    30. return heap[1];
    31. }
    32. public void heapSort(T[] arr) {
    33. heapify(arr); // 初始化堆
    34. for (int i = size; i > 0; i--) {
    35. arr[i - 1] = deleteMax(); // 依次取出堆顶元素
    36. }
    37. }
    38. private void swim(int k) {
    39. while (k > 1 && heap[k].compareTo(heap[k / 2]) > 0) { // 父节点小于当前节点,上滤
    40. swap(k, k / 2);
    41. k /= 2; // 移动到父节点
    42. }
    43. }
    44. private void sink(int k) {
    45. while (2 * k <= size) { // 如果有左孩子
    46. int j = 2 * k;
    47. if (j < size && heap[j].compareTo(heap[j + 1]) < 0) { // 选择左右孩子中较大的那个
    48. j++;
    49. }
    50. if (heap[k].compareTo(heap[j]) >= 0) { // 如果父节点不小于孩子节点,下滤结束
    51. break;
    52. }
    53. swap(k, j); // 父节点和子节点交换
    54. k = j; // 移动到子节点
    55. }
    56. }
    57. private void heapify(T[] arr) {
    58. heap = (T[]) new Comparable[arr.length + 1];
    59. size = arr.length;
    60. System.arraycopy(arr, 0, heap, 1, arr.length); // 复制数组元素到堆中
    61. for (int i = size / 2; i >= 1; i--) { // 倒序下滤,从最后一个非叶子节点开始
    62. sink(i); // 下滤操作
    63. }
    64. }
    65. private void resize() {
    66. int newSize = heap.length * 2;
    67. heap = Arrays.copyOf(heap, newSize);
    68. }
    69. private void swap(int i, int j) {
    70. T temp = heap[i];
    71. heap[i] = heap[j];
    72. heap[j] = temp;
    73. }
    74. }

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

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

    1. MaxHeap maxHeap = new MaxHeap<>(10);
    2. maxHeap.insert(3);
    3. maxHeap.insert(1);
    4. maxHeap.insert(4);
    5. maxHeap.insert(1);
    6. maxHeap.insert(5);
    7. System.out.println(maxHeap.deleteMax()); // 输出:5
    8. System.out.println(maxHeap.getMax()); // 输出:4
    9. Integer[] arr = {3, 1, 4, 1, 5};
    10. maxHeap.heapSort(arr);
    11. System.out.println(Arrays.toString(arr)); // 输出:[1, 1, 3, 4, 5]

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

  • 相关阅读:
    java毕业设计《数据结构与算法》网上教学系统mybatis+源码+调试部署+系统+数据库+lw
    MATLAB变量
    数商云B2B商城系统订货功能为新能源汽车行业赋能,打造高质量发展生态圈
    upload-labs1-21关文件上传通关手册
    【附代码案例】深入理解 PyTorch 张量:叶子张量与非叶子张量
    kubernetes(K8S)学习笔记P4:K8s核心概念1
    vue.js 短连接 动态连接
    计算机组原,系统总线,总线概念,结构,分类,特性指标,举例
    在不使用PageHelper或Mybatis的情况下实现手动分页
    Python - Windows下使用Python脚本同步一个文件夹下的所有文件到另一个文件夹下
  • 原文地址:https://blog.csdn.net/m0_37649480/article/details/134539959