首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何从列表/集合和自定义比较器在Java中的O(N)中创建优先级队列

如何从列表/集合和自定义比较器在Java中的O(N)中创建优先级队列
EN

Stack Overflow用户
提问于 2021-09-07 17:49:59
回答 1查看 677关注 0票数 3

我希望使用自定义比较器从ArrayList创建一个优先级队列。

代码语言:javascript
运行
复制
public PriorityQueue(Collection<? extends E> c, Comparator<? super E> comparator))

但是在PriorityQueue中没有这样的构造函数。

我可以看到这些构造函数,但没有找到像heapify()那样在O(n)中这样做的方法。

  1. 首先使用构造函数创建一个PQ,然后使用addAll(...)添加。addAll()将是O(nlogn),因为addAll()内部为输入集合的每个元素调用add()
代码语言:javascript
运行
复制
PriorityQueue<Foo> priorityQueue = new PriorityQueue<>(inputList.size(), comparator);
priorityQueue.addAll(inputList); 
  1. 通过集合构造函数创建PQ :它没有设置比较器的方法
代码语言:javascript
运行
复制
PriorityQueue<Foo> priorityQueue = new PriorityQueue<>(inputList); 
EN

回答 1

Stack Overflow用户

发布于 2021-09-08 23:55:30

一种方法是子类PriorityQueue并添加所需的构造函数。然后在子类中存储集合数组的副本,并重写PriorityQueue#toArray以返回存储的集合的数组。最后,使用PriorityQueue构造函数构造PriorityQueue(PriorityQueue<> pq),最终调用PriorityQueue#heapify,后者使用PriorityQueue#siftDown而不是PriorityQueue#siftUp。这将实现所需的O(N)复杂性。

下面是一个使用构建器类封装(隐藏) PriorityQueue子类的示例实现:

代码语言:javascript
运行
复制
/**
 * Builder class used to create a {@code PriorityQueue<E>} from a
 * {@code Collection<? extends E>} and a {@code Comparator<? super E>} in
 * {@code O(N)} time.
 * 
 * @see PriorityQueueBuilder#build(Collection, Comparator)
 */
public final class PriorityQueueBuilder {
    
    /** Don't subclass this class. */
    private PriorityQueueBuilder() {}
    
    /**
     * Creates a priority queue using a specified collection and comparator in
     * {@code O(N)} time.
     * 
     * @param <E> - the priority queue's type
     * @param c - the collection to create the priority queue with
     * @param comparator - the comparator to be used by the priority queue
     * @return a priority queue created from the specified collection and
     *         comparator
     * @throws NullPointerException if the specified collection is {@code null}
     */
    public static <E> PriorityQueue<E> build(Collection<? extends E> c, Comparator<? super E> comparator) {
        return new PriorityQueue<>(new NPriorityQueue<>(c, comparator));
    }
    
    
    /**
     * Temporary priority queue implementation used to create an actual
     * {@code PriorityQueue<E>}.
     * 
     * We extend {@code PriorityQueue} in order to use the 
     * {@code PriorityQueue(PriorityQueue<? extends E> pq)} constructor rather 
     * than its {@code PriorityQueue(Collection<? extends E> c)} constructor
     */
    private static class NPriorityQueue<E> extends PriorityQueue<E> {
        
        private Object[] nQueue;
        
        /**
         * Sets the comparator and makes a copy of the collections underlying
         * object array.
         */
        public NPriorityQueue(Collection<? extends E> c, Comparator<? super E> comparator) {
            super(comparator);
            
            nQueue = c.toArray();
        }
        
    

       /**
         * Returns an array containing all of the elements in this queue.
         * The elements are in no particular order.
         * 
         * We need to override this method in order to return our
         * {@code nQueue} rather than {@code PriorityQueue}'s
         * {@code queue}. {@code PriorityQueue} calls this method to construct
         * the queue in {@code initElementsFromCollection}.
         *
         * @return an array containing all of the elements in this queue
         */
        @Override
        public Object[] toArray() {
            // no need to return a copy, just pass along the reference
            return nQueue;
        }
        
    }
    
}

下面是一个测试上述方法的类:

代码语言:javascript
运行
复制
public class Driver {
    
    public static final int RANGE_START = 1;
    public static final int RANGE_END = 10;
    
    /**
     * Entry point of the program.
     * @param args - command line arguments
     */
    public static void main(String[] args) {
        List<Integer> list = IntStream.rangeClosed(RANGE_START, RANGE_END)
                .boxed()
                .collect(Collectors.toList());
        
        Collections.shuffle(list);
        
        PriorityQueue<Integer> pq = PriorityQueueBuilder.build(list, getComparator());
        
        outputList(list);
        outputPriorityQueue(pq);
    }
    
    private static Comparator<Integer> getComparator() {
        return new Comparator<Integer>()
        {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 - o2;
            }
        };
    }
    
    private static void outputList(List<?> l) {
        System.out.print("         List: ");
        l.forEach(e -> System.out.printf("%2d ", e));
        System.out.println();
    }
    
    private static void outputPriorityQueue(PriorityQueue<?> pq) {
        System.out.print("PriorityQueue: ");
        while (!pq.isEmpty()) {
            System.out.printf("%2d ", pq.poll());
        }
        System.out.println();
    }
    
}

下面是运行测试类的输出:

代码语言:javascript
运行
复制
         List:  4  8  3  7 10  2  9  5  6  1 
PriorityQueue:  1  2  3  4  5  6  7  8  9 10 
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69092605

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档