Java建小根堆

在数据结构中,堆是一种特殊的完全二叉树,通常用于实现优先队列。小根堆则是指任意节点的值都不大于其子节点的值。小根堆的根节点总是对所有节点来说是最小的元素,这使得在小根堆中获取最小值的操作非常高效。

小根堆的基本特性:

  1. 每个节点的值小于或等于其子节点的值。
  2. 完全二叉树,所有层都被填满,且最后一层从左到右填充。

在 Java 中,我们可以使用数组来实现小根堆。以下是构建小根堆的一些步骤:

  1. 插入元素:将新元素添加到堆的末尾,并向上调整以保持小根堆的性质。
  2. 删除最小元素:取出堆顶元素,然后将最后一个元素移动到堆顶,并向下调整以恢复小根堆的性质。
  3. 调整堆:对于插入或删除后的位置,可以使用向上或向下的方法调整堆的结构。

小根堆的实现

下面是一个简单的小根堆的实现代码示例:

import java.util.Arrays;

public class MinHeap {
    private int[] heap;
    private int size;
    private int capacity;

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

    // 获取父节点索引
    private int parent(int index) {
        return (index - 1) / 2;
    }

    // 获取左子节点索引
    private int leftChild(int index) {
        return 2 * index + 1;
    }

    // 获取右子节点索引
    private int rightChild(int index) {
        return 2 * index + 2;
    }

    // 向上调整
    private void siftUp(int index) {
        while (index > 0 && heap[parent(index)] > heap[index]) {
            swap(index, parent(index));
            index = parent(index);
        }
    }

    // 向下调整
    private void siftDown(int index) {
        int minIndex = index;

        int left = leftChild(index);
        if (left < size && heap[left] < heap[minIndex]) {
            minIndex = left;
        }

        int right = rightChild(index);
        if (right < size && heap[right] < heap[minIndex]) {
            minIndex = right;
        }

        if (index != minIndex) {
            swap(index, minIndex);
            siftDown(minIndex);
        }
    }

    // 插入元素
    public void insert(int value) {
        if (size == capacity) throw new RuntimeException("Heap is full");
        heap[size] = value;
        size++;
        siftUp(size - 1);
    }

    // 删除最小元素
    public int extractMin() {
        if (size == 0) throw new RuntimeException("Heap is empty");
        int min = heap[0];
        heap[0] = heap[size - 1];
        size--;
        siftDown(0);
        return min;
    }

    // 交换元素
    private void swap(int i, int j) {
        int temp = heap[i];
        heap[i] = heap[j];
        heap[j] = temp;
    }

    // 调试输出
    public void printHeap() {
        System.out.println(Arrays.toString(Arrays.copyOf(heap, size)));
    }
}

小根堆的使用

我们可以在 main 方法中演示小根堆的使用:

public static void main(String[] args) {
    MinHeap minHeap = new MinHeap(10);
    minHeap.insert(5);
    minHeap.insert(3);
    minHeap.insert(8);
    minHeap.insert(1);
    
    minHeap.printHeap(); // 输出堆的当前状态

    System.out.println("最小值: " + minHeap.extractMin());
    minHeap.printHeap(); // 再次输出堆的当前状态
}

状态图

在插入和删除过程中,小根堆的状态可以通过状态图进行可视化。以下是一个简单的状态图示例:

stateDiagram
    [*] --> 初始状态
    初始状态 --> 插入状态: 插入元素
    插入状态 --> 调整状态: 向上调整
    调整状态 --> [*]
    [*] --> 删除状态: 删除最小元素
    删除状态 --> 调整状态: 向下调整
    调整状态 --> [*]

结论

小根堆是一个高效的数据结构,适合用于优先级队列和实时操作中获取最小值。通过以上的示例,您可以了解小根堆的基本实现逻辑和操作。在实际应用中,堆的特性可以帮助我们更好地管理和访问数据,特别是在需要频繁插入和删除元素的场景。希望本文的介绍能帮助你更好地理解小根堆的构建与应用。