优先队列(PriorityQueue)

概念

普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。通常采用堆数据结构来实现。

优先队列的实现:优先队列通常用堆来实现。因为通常所说的二叉堆(堆分为很多种:二叉堆,斐波拉契堆,严格斐波拉契堆等)每次插入或删除元素都会自动维持优先级的先后。

堆的具体概念在《堆排序》这篇文章中详细介绍过。

Java中的实现

在Java语言中提供优先队列的实现(PriorityQueue)。

  • PriorityQueue基于优先级堆的无限优先级queue优先级队列的元素根据它们的有序natural ordering ,或由一个Comparator在队列构造的时候提供,这取决于所使用的构造方法。 优先队列不允许null元素。 依靠自然排序的优先级队列也不允许插入不可比较的对象(这样做可能导致ClassCastException )。该队列的头部是相对于指定顺序的最小元素。 如果多个元素被绑定到最小值,那么头就是这些元素之一 - 关系被任意破坏。 队列检索操作pollremovepeekelement访问在队列的头部的元件。

Java提供的PriorityQueue是一个基于小顶堆实现的优先队列,在这个队列中每次出操作都是返回的该队列中最小的那个元素。至于传入对象的方法怎么比较“大小”,一种是传入能自然排序的对象,例如:Integer、Long、Character、String等,如果是自定义类,则必须实现Comparator接口。

优先队列的应用

在经典的TopK问题中,通常就可以用优先队列来解决问题。

题目大致意思:给定一个超级大的流式数据(这里理解为不能将所有数据全部保存在内存中的数据规模),我们需要找到这个流式数据中的最大的K个值。

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int K = scanner.nextInt();//需要维持最大值的数目
        scanner.nextLine();
        PriorityQueue<Integer> pq = new PriorityQueue<>();//优先队列(小顶堆)
        while (true) {
            int v = scanner.nextInt();
            if (v == -1) {//输出-1表示停止输入,输出结果
                System.out.println(pq.toString());
            } else {
                if (pq.size() < K) {
                    pq.add(v);
                }else if(pq.peek()<v){
                    pq.poll();
                    pq.add(v);
                }
            }
        }
    }
}

 

posted @ 2019-04-26 10:38  听到微笑  阅读(1)  评论(0编辑  收藏  举报  来源