Java 大根堆实现

发布于 2024-01-13  572 次阅读


Java中大根堆或者小根堆的实现

Java中有大根堆(Max Heap)和小根堆(Min Heap)的实现,它们通常是通过优先队列(PriorityQueue)来实现的。PriorityQueue是Java集合框架中的一部分,它可以实现优先级队列的功能,根据元素的优先级进行排序。

在默认情况下,PriorityQueue是小根堆(最小堆),也就是说,队列的头部元素是最小的元素。如果你想要实现大根堆,可以通过提供一个自定义的Comparator来实现。这个Comparator定义了元素之间的比较规则。

以下是一个简单的示例,演示了如何使用PriorityQueue来实现大根堆:

import java.util.PriorityQueue;
import java.util.Comparator;

public class MaxHeapExample {
    public static void main(String[] args) {
        // 创建一个大根堆(最大堆)
        PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Comparator.reverseOrder());

        // 添加元素
        maxHeap.add(5);
        maxHeap.add(2);
        maxHeap.add(8);
        maxHeap.add(1);

        // 获取并移除最大元素
        while (!maxHeap.isEmpty()) {
            System.out.println(maxHeap.poll());
        }
    }
}

在上述示例中,通过使用Comparator.reverseOrder()来创建一个逆序的比较器,从而将默认的小根堆转换为大根堆。

需要注意的是,PriorityQueue并不是线程安全的,如果在多线程环境下使用,可能需要考虑同步操作或选择线程安全的实现。如果需要在多线程环境下使用堆,可以考虑使用java.util.concurrent.PriorityBlockingQueue

PriorityQueue是基于二叉堆(Binary Heap)实现的,具体是一个最小堆(Min Heap)。在Java中,PriorityQueue的操作时间复杂度如下:

  1. 插入(add): O(log n)

    • 插入操作涉及到将新元素添加到堆的底部,然后执行一系列上升操作,确保堆的性质仍然得以保持。
  2. 删除最小元素(poll): O(log n)

    • 删除最小元素(堆顶元素)操作包括将堆的最后一个元素移动到堆顶,然后执行一系列下降操作,确保堆的性质。
  3. 检查最小元素(peek): O(1)

    • 查看堆顶元素,由于最小元素总是位于堆顶,因此这是一个常数时间的操作。
  4. 删除特定元素(remove): O(n)

    • 删除特定元素的操作需要先找到该元素的位置,然后执行删除并重新调整堆的操作。在最坏情况下,需要线性时间。

总体而言,PriorityQueue对于插入和删除最小元素的操作具有较好的性能。它适用于需要在动态数据集中快速找到最小元素的场景。然而,对于需要随机访问、删除特定元素等操作的场景,可能需要考虑其他数据结构。

重定义排序规则

如果你想使用 PriorityQueueNode 类的 value 值上进行排序,你可以在创建 PriorityQueue 对象时,提供一个自定义的比较器(Comparator),以确保根据 value 值来进行排序。下面是一个简单的例子:

import java.util.PriorityQueue;
import java.util.Comparator;

class Node {
    int value;

    // 构造函数等其他成员...

    // Getter方法
    public int getValue() {
        return value;
    }
}

public class PriorityQueueExample {
    public static void main(String[] args) {
        // 创建一个根据Node的value值降序排列的PriorityQueue
        PriorityQueue<Node> maxHeap = new PriorityQueue<>(Comparator.comparing(Node::getValue).reversed());

        // 添加一些Node对象
        maxHeap.add(new Node(5));
        maxHeap.add(new Node(2));
        maxHeap.add(new Node(8));
        maxHeap.add(new Node(1));

        // 获取并移除最大元素
        while (!maxHeap.isEmpty()) {
            Node node = maxHeap.poll();
            System.out.println("Node value: " + node.getValue());
        }
    }
}

在上述示例中,Comparator.comparing(Node::getValue).reversed() 创建了一个比较器,该比较器将根据 Node 对象的 value 值降序排列。通过提供这个比较器给 PriorityQueue 构造函数,你就能够实现根据 value 值排序的大根堆。

请确保在 Node 类中提供了适当的构造函数和获取 value 的方法,以便使用。