最小堆是啥?PriorityQueue为啥是最小堆?

280 阅读2分钟

最小堆的定义

最小堆是一种特殊的完全二叉树,属于堆数据结构的一种。它具有以下两个关键特性:

  1. 结构性:最小堆是一棵完全二叉树,这意味着除了最后一层外,每一层都被完全填充,并且最后一层的节点从左到右依次排列。
  2. 有序性:对于堆中的任意节点,其值都小于或等于它的子节点的值。也就是说,根节点存储的是堆中的最小值。

以下是一个简单的最小堆示例:

       1
     /   \
    2     3
   / \   / \
  4   5 6   7

在这个最小堆中,根节点 1 是最小值,且每个节点的值都小于其子节点的值。

Java 中 PriorityQueue 是最小堆的原因

在 Java 里,PriorityQueue 默认是一个最小堆。这是由它的设计和实现所决定的:

  • 默认比较器PriorityQueue 在创建时如果没有指定比较器,会使用元素的自然顺序。对于实现了 Comparable 接口的元素,会按照其 compareTo 方法的规则进行排序,从而保证队列头部(也就是堆的根节点)是最小元素。
  • 插入和删除操作的实现PriorityQueue 的插入和删除操作会维护堆的有序性。当插入一个新元素时,会将其放在堆的末尾,然后通过上浮操作调整堆结构,确保新元素被放到合适位置;删除元素时,通常是删除堆顶元素,之后会将堆的最后一个元素移到堆顶,再通过下沉操作重新调整堆结构。

下面是一个简单的 Java 代码示例,展示了 PriorityQueue 作为最小堆的使用:

import java.util.PriorityQueue;

public class MinHeapExample {
    public static void main(String[] args) {
        // 创建一个 PriorityQueue 实例
        PriorityQueue<Integer> minHeap = new PriorityQueue<>();

        // 向堆中添加元素
        minHeap.add(3);
        minHeap.add(1);
        minHeap.add(2);

        // 依次取出堆顶元素
        while (!minHeap.isEmpty()) {
            System.out.println(minHeap.poll());
        }
    }
}

在上述代码中,我们创建了一个 PriorityQueue 实例,向其中添加了 3 个元素。当我们依次取出堆顶元素时,输出的顺序是 1、2、3,这表明 PriorityQueue 确实是按照最小堆的规则进行排序的。