数据结构-最小堆使用教程

堆(Heap)是一种特殊的完全二叉树,所有的节点都遵循堆的属性。在一个最大堆中,每个节点的值都大于或等于其子节点的值,而在一个最小堆中,每个节点的值都小于或等于其子节点的值。堆常用于实现优先队列,并且是堆排序算法的核心数据结构。

以下是使用Java实现一个最小堆的例子:

定义最小堆

public class MinHeap {
    private int[] Heap;
    private int size;
    private int maxsize;

    public MinHeap(int maxsize) {
        this.maxsize = maxsize;
        this.size = 0;
        Heap = new int[this.maxsize + 1];
        Heap[0] = Integer.MIN_VALUE; // 将堆数组的第一个元素设置为最小值,以便能使用简单整数除法找到父节点和子节点
    }

    // 返回当前节点的父节点位置
    private int parent(int pos) {
        return pos / 2;
    }

    // 返回左子节点的位置
    private int leftChild(int pos) {
        return (2 * pos);
    }

    // 返回右子节点的位置
    private int rightChild(int pos) {
        return (2 * pos) + 1;
    }

    // 交换两个节点的值
    private void swap(int fpos, int spos) {
        int tmp;
        tmp = Heap[fpos];
        Heap[fpos] = Heap[spos];
        Heap[spos] = tmp;
    }

    // 如果当前节点的值小于其父节点,则向上移动(用于插入操作)
    private void minHeapifyUp(int pos) {
        int temp = Heap[pos];
        while (pos > 1 && Heap[parent(pos)] > temp) {
            Heap[pos] = Heap[parent(pos)];
            pos = parent(pos);
        }
        Heap[pos] = temp;
    }

    // 如果当前节点的值大于其子节点之一,则向下移动(用于删除操作)
    private void minHeapifyDown(int pos) {
        int smallest = pos;
        int left = leftChild(pos);
        int right = rightChild(pos);

        if (left <= size && Heap[left] < Heap[smallest]) {
            smallest = left;
        }
        if (right <= size && Heap[right] < Heap[smallest]) {
            smallest = right;
        }

        if (smallest != pos) {
            swap(pos, smallest);
            minHeapifyDown(smallest);
        }
    }

    // 插入一个元素
    public void insert(int element) {
        if (size >= maxsize) {
            return; // 堆已满
        }
        Heap[++size] = element;
        minHeapifyUp(size);
    }

    // 移除并返回最小元素
    public int extractMin() {
        if (size == 0) {
            throw new NoSuchElementException("Heap is empty");
        }
        int min = Heap[1];
        Heap[1] = Heap[size--];
        minHeapifyDown(1);
        return min;
    }
}

使用最小堆

public class Main {
    public static void main(String[] args) {
        MinHeap minHeap = new MinHeap(10);
        minHeap.insert(5);
        minHeap.insert(3);
        minHeap.insert(17);
        minHeap.insert(10);
        minHeap.insert(84);
        minHeap.insert(19);
        minHeap.insert(6);
        minHeap.insert(22);
        minHeap.insert(9);

        // 提取最小值,也就是根节点的值
        System.out.println("The Min val is " + minHeap.extractMin());  // 输出 3
    }
}

在上面的示例中,我们定义了一个最小堆,并实现了insert方法来向堆中添加元素,以及extractMin方法来删除并返回堆中的最小元素。堆的性质通过minHeapifyUpminHeapifyDown方法进行维护。

在实际应用中,Java标准库提供了PriorityQueue类,它内部使用了堆数据结构,通常可以直接使用这个类,而不必自己实现堆。例如:

PriorityQueue<Integer> minHeap = new PriorityQueue<>();
minHeap.add(5);
minHeap.add(3);
minHeap.add(17);
// ...
int min = minHeap.poll(); // 自动获取并删除最小元素

PriorityQueue类在默认情况下实现了最小堆,如果需要最大堆,则可以提供自定义的比较器。使用PriorityQueue不仅减少了开发时间,而且因为它是经过充分测试和优化的,所以在性能上通常也会更好。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员爱学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值