简体   繁体   English

Java PriorityQueue:如何使用自定义比较器堆积集合?

[英]Java PriorityQueue: how to heapify a Collection with a custom Comparator?

For example, given a List of Integer List<Integer> list = Arrays.asList(5,4,5,2,2) , how can I get a maxHeap from this List in O(n) time complexity?例如,给定一个 Integer List<Integer> list = Arrays.asList(5,4,5,2,2)的列表,如何在O(n)时间复杂度内从该列表中获得一个maxHeap

The naive method:天真的方法:

PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder());
for (Integer i : list) {
    maxHeap.offer(i);
}

However, the time complexity is O(nlogn) .但是,时间复杂度为O(nlogn)

We can trigger the heapify method by using the following constructor:我们可以使用以下构造函数来触发 heapify 方法:

PriorityQueue<Integer> maxHeap = new PriorityQueue<>(list);

The time complexity is O(n) .时间复杂度为O(n) However, it forces me to use the natural order which is the minHeap .但是,它迫使我使用自然顺序,即minHeap

My Question:我的问题:

How can I construct a PriorityQueue by heapifying a Collection with custom Comparator?如何通过使用自定义比较器堆积集合来构造 PriorityQueue?

Ref: Java doc of PriorityQueue参考: PriorityQueue 的 Java 文档

PS: @user207421 PS:@user207421
Heapify algorithm can transform any unsorted array into a heap in O(n) time, not O(nlogn) . Heapify 算法可以在O(n)时间内将任何未排序的数组转换为堆,而不是O(nlogn) There are many articles about heapify , also in CLRS's Introduction to Algorithms Page 159, build a heap from any unsorted array is O(n) . 有很多关于 heapify 的文章,也在 CLRS 的算法简介第 159 页中,从任何未排序的数组构建堆是O(n) And heap is also not a sorted array.而且堆也不是排序数组。 It's a complete tree with heap property which can be encoded in array.它是一棵具有堆属性的完整树,可以在数组中编码。

If you don't mind some hack如果你不介意一些黑客

According to the java doc of PriorityQueue(PriorityQueue)根据PriorityQueue(PriorityQueue) 的 java doc

Creates a PriorityQueue containing the elements in the specified priority queue.创建一个包含指定优先级队列中元素的 PriorityQueue。 This priority queue will be ordered according to the same ordering as the given priority queue.此优先级队列将按照与给定优先级队列相同的顺序进行排序。

So we can extend PriorityQueue as CustomComparatorPriorityQueue to hold the desired comparator and the Collection we need to heapify.因此我们可以将PriorityQueue扩展为CustomComparatorPriorityQueue来保存所需的比较器和我们需要堆化的 Collection。 Then call new PriorityQueue(PriorityQueue) with an instance of CustomComparatorPriorityQueue .然后使用CustomComparatorPriorityQueue的实例调用 new PriorityQueue(PriorityQueue)

Below is tested to work in Java 15.下面经过测试可以在 Java 15 中运行。

import java.util.*;

public class CustomComparatorPriorityQueue<T> extends PriorityQueue<T> {
    private Collection<T> wrapped;

    public static <U> PriorityQueue<U> create(Collection<U> wrapped, Comparator<U> custom) {
        return new PriorityQueue<U>(new CustomComparatorPriorityQueue<>(wrapped, custom));
    }

    private CustomComparatorPriorityQueue(Collection<T> wrapped, Comparator<T> custom) {
        super(custom);
        this.wrapped = wrapped;
    }

    @Override
    public Object[] toArray() {
        return wrapped.toArray();
    }

    public static void main(String[] args) {
        List<Integer> a = Arrays.asList(3, 6, 4, 8, 1, 9);
        PriorityQueue<Integer> pq = CustomComparatorPriorityQueue.create(a, Comparator.<Integer>naturalOrder().reversed());
        Integer b;
        while ((b = pq.poll()) != null) {
            System.out.println(b);
        }
    }

    // Override to don't allow other purpose...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM