当前位置:首页 > Java

java 如何表示堆

2026-03-22 18:03:42Java

堆的基本概念

堆是一种特殊的完全二叉树,分为最大堆和最小堆。最大堆中父节点的值大于或等于子节点的值,最小堆中父节点的值小于或等于子节点的值。堆常用于优先队列和堆排序等场景。

使用数组表示堆

堆通常用数组实现,利用完全二叉树的性质可以高效地通过索引访问父节点和子节点。对于数组中索引为i的节点:

java 如何表示堆

  • 父节点索引:(i - 1) / 2
  • 左子节点索引:2 * i + 1
  • 右子节点索引:2 * i + 2
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;
    heapifyUp(size);
    size++;
}

private void heapifyUp(int index) {
    int parent = (index - 1) / 2;
    while (index > 0 && heap[index] > heap[parent]) {
        swap(index, parent);
        index = parent;
        parent = (index - 1) / 2;
    }
}

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

删除堆顶元素 将堆顶元素与末尾元素交换,移除末尾元素后通过“下沉”操作调整堆结构:

java 如何表示堆

public int extractMax() {
    if (size == 0) {
        throw new IllegalStateException("Heap is empty");
    }
    int max = heap[0];
    heap[0] = heap[size - 1];
    size--;
    heapifyDown(0);
    return max;
}

private void heapifyDown(int index) {
    int left = 2 * index + 1;
    int right = 2 * index + 2;
    int largest = index;

    if (left < size && heap[left] > heap[largest]) {
        largest = left;
    }
    if (right < size && heap[right] > heap[largest]) {
        largest = right;
    }
    if (largest != index) {
        swap(index, largest);
        heapifyDown(largest);
    }
}

使用优先队列实现堆

Java的PriorityQueue类默认实现最小堆,可通过自定义比较器实现最大堆:

// 最小堆(默认)
PriorityQueue<Integer> minHeap = new PriorityQueue<>();

// 最大堆
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder());

堆的应用示例

堆排序 利用堆的性质实现排序:

public void heapSort(int[] arr) {
    int n = arr.length;
    // 构建最大堆
    for (int i = n / 2 - 1; i >= 0; i--) {
        heapify(arr, n, i);
    }
    // 逐个提取元素
    for (int i = n - 1; i > 0; i--) {
        swap(arr, 0, i);
        heapify(arr, i, 0);
    }
}

private void heapify(int[] arr, int n, int i) {
    int largest = i;
    int left = 2 * i + 1;
    int right = 2 * i + 2;

    if (left < n && arr[left] > arr[largest]) {
        largest = left;
    }
    if (right < n && arr[right] > arr[largest]) {
        largest = right;
    }
    if (largest != i) {
        swap(arr, i, largest);
        heapify(arr, n, largest);
    }
}

标签: 表示java
分享给朋友:

相关文章

如何编译java文件

如何编译java文件

安装JDK 确保系统已安装Java Development Kit(JDK)。可通过命令行输入 javac -version 和 java -version 验证。若未安装,需从Oracle或Open…

java如何导包

java如何导包

导入包的方法 在Java中,导入包(package)可以通过import语句实现,用于引入其他类或包中的功能。以下是几种常见的导包方式: 导入单个类 import java.util.ArrayL…

java如何实现异步

java如何实现异步

Java实现异步的方法 Java中实现异步编程可以通过多种方式,每种方式适用于不同的场景和需求。以下是常见的实现方法: 使用Thread类 创建新线程执行异步任务是最基础的方式。通过继承Thread…

java如何解决高并发

java如何解决高并发

Java 高并发解决方案 使用线程池优化资源管理 线程池(如 ThreadPoolExecutor)能避免频繁创建和销毁线程的开销。通过核心线程数、最大线程数和任务队列的合理配置,可以平衡系统负载。例…

如何选择java培训

如何选择java培训

评估培训机构资质 选择有正规资质的机构,查看其营业执照、办学许可证等。优先考虑具备人力资源和社会保障部或教育部认证的机构,这类机构的教学质量和课程设置通常更规范。 考察课程内容与行业需求匹配度…

vue实现java登录注册

vue实现java登录注册

实现 Vue 与 Java 后端的登录注册功能 前端 Vue 部分 安装必要的依赖(如 axios 用于 HTTP 请求): npm install axios 创建登录表单组件(Login.vue…