本文主要是介绍优先队列(PriorityQueue),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
概念
普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。通常采用堆数据结构来实现。
优先队列的实现:优先队列通常用堆来实现。因为通常所说的二叉堆(堆分为很多种:二叉堆,斐波拉契堆,严格斐波拉契堆等)每次插入或删除元素都会自动维持优先级的先后。
堆的具体概念在《堆排序》这篇文章中详细介绍过。
Java中的实现
在Java语言中提供优先队列的实现(PriorityQueue)。
PriorityQueue基于优先级堆的无限优先级queue 。 优先级队列的元素根据它们的有序natural ordering ,或由一个
Comparator
在队列构造的时候提供,这取决于所使用的构造方法。 优先队列不允许null
元素。 依靠自然排序的优先级队列也不允许插入不可比较的对象(这样做可能导致ClassCastException
)。该队列的头部是相对于指定顺序的最小元素。 如果多个元素被绑定到最小值,那么头就是这些元素之一 - 关系被任意破坏。 队列检索操作poll
,remove
,peek
和element
访问在队列的头部的元件。
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);}}}}
}
这篇关于优先队列(PriorityQueue)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!