PriorityQueue是个基于优先级堆的极大优先级队列
<wbr>。<br><strong><wbr>此队列按照在构造时所指定的顺序对元素排序,既可以根据元素的自然顺序来指定排序(参阅Comparable),<br>
也可以根据Comparator来指定</wbr></strong><wbr>,这取决于使用哪种构造方法。优先级队列不允许null元素。<br>
依靠自然排序的优先级队列还不允许插入不可比较的对象(这样做可能导致ClassCastException)。<br>
此队列的头是按指定排序方式的<strong><wbr>最小元素</wbr></strong><wbr>。如果多个元素都是最小值,则头是其中一个元素——选择方法是任意的。<br>
队列检索操作poll、remove、peek和element访问处于队列头的元素。<br>
优先级队列是无界的,但是有一个<strong><wbr>内部容量</wbr></strong><wbr>,控制着用于存储队列元素的数组的大小。<br>
它总是至少与队列的大小相同。随着不断向优先级队列添加元素,其容量会自动增加。无需指定容量增加策略的细节。<br><strong><wbr>注意1</wbr></strong><wbr>:该队列是用<strong><wbr>数组实现</wbr></strong><wbr>,但是数组大小可以<strong><wbr>动态增加,容量无限</wbr></strong><wbr>。<br><strong><wbr>注意2</wbr></strong><wbr>:此实现不是同步的。<strong><wbr>不是线程安全的</wbr></strong><wbr>。如果多个线程中的任意线程从结构上修改了列表,则这些线程不应同时访问PriorityQueue实例,这时请使用<strong><wbr>线程安全的PriorityBlockingQueue类</wbr></strong><wbr>。<br><strong><wbr>注意3</wbr></strong><wbr>:不允许使用<strong><wbr>null元素</wbr></strong><wbr>。<br><strong><wbr>注意4</wbr></strong><wbr>:此实现为插入方法(offer、poll、remove()和add方法)提供O(log(n))时间;<br>
为remove(Object)和contains(Object)方法提供线性时间;<br>
为检索方法(peek、element和size)提供固定时间。<br><strong><wbr>注意5</wbr></strong><wbr>:方法iterator()中提供的迭代器并<strong><wbr>不保证以有序的方式遍历优先级队列中的元素</wbr></strong><wbr>。<br>
至于原因可参考下面关于PriorityQueue的内部实现<br>
如果需要按顺序遍历,请考虑使用Arrays.sort(pq.toArray())。<br><strong><wbr>注意6</wbr></strong><wbr>:<strong><wbr>可以在构造函数中指定如何排序</wbr></strong><wbr>。如:<br>
PriorityQueue()<br>
使用默认的初始容量(11)创建一个PriorityQueue,并根据其自然顺序来排序其元素(使用<strong><wbr>Comparable</wbr></strong><wbr>)。<br>
PriorityQueue(intinitialCapacity)<br>
使用指定的初始容量创建一个PriorityQueue,并根据其自然顺序来排序其元素(使用<strong><wbr>Comparable</wbr></strong><wbr>)。<br>
PriorityQueue(intinitialCapacity,Comparator<?superE>comparator)<br>
使用指定的初始容量创建一个PriorityQueue,并根据指定的比较器<strong><wbr>comparator</wbr></strong><wbr>来排序其元素。<br>
注意7:此类及其迭代器实现了Collection和Iterator接口的所有可选方法。<br><strong><wbr>PriorityQueue的内部实现<br>
PriorityQueue对元素采用的是堆排序,头是按指定排序方式的最小元素。堆排序只能保证根是最大(最小),整个堆并不是有序的。</wbr></strong><wbr><br><strong><wbr>方法iterator()中提供的迭代器可能只是对整个数组的依次遍历。也就只能保证数组的第一个元素是最小的</wbr></strong><wbr>。<br>
实例1的结果也正好与此相符。<br>
实例1:<br>
publicstaticvoidmain(String[]args){<br>
PriorityQueue<String>pq=newPriorityQueue<String>();<br>
pq.add("dog");<br>
pq.add("apple");<br>
pq.add("fox");<br>
pq.add("easy");<br>
pq.add("boy");<br><br>
while(!pq.isEmpty()){<br>
System.out.print("left:");<br>
for(Strings:pq){<br>
System.out.print(s+"");<br>
}<br>
System.out.println();<br>
System.out.println("poll():"+pq.poll());<br>
}<br>
}<br>
输出的结果如下:<br>
left:appleboyfoxeasydog<br>
poll():apple<br>
left:boydogfoxeasy<br>
poll():boy<br>
left:dogeasyfox<br>
poll():dog<br>
left:easyfox<br>
poll():easy<br>
left:fox<br>
poll():fox<br>
可以看到,<strong><wbr>虽然PriorityQueue保持了队列顶部元素总是最小,但内部的其它元素的顺序却随着元素的减少始终处于变化之中</wbr></strong><wbr>。<br>
察看源代码来一探究竟。从Netbeans中非常方便的连接到PriorityQueue的add函数实现,<br>
最终跟踪到函数privatevoidsiftUpComparable(intk,Ex),定义如下:<br>
privatevoidsiftUpComparable(intk,Ex){<br>
Comparable<?superE>key=(Comparable<?superE>)x;<br>
while(k>0){<br>
intparent=(k-1)>>>1;<br>
Objecte=queue[parent];<br>
if(key.compareTo((E)e)>=0)<br>
break;<br>
queue[k]=e;<br>
k=parent;<br>
}<br>
queue[k]=key;<br>
}<br>
相对于add的操作,该函数的入口参数k是指新加入元素的下标,而x就是新加入的元素。<br>
乍一看,这个函数的实现比较令人费解,尤其是parent的定义。通过进一步分析了解到,<br>
PriorityQueue内部成员数组queue其实是实现了一个二叉树的数据结构,这棵二叉树的根节点是queue[0],<br>
左子节点是queue[1],右子节点是queue[2],而queue[3]又是queue[1]的左子节点,依此类推,给定元素queue<wbr>,<br>
该节点的父节点是queue[(i-1)/2]。因此parent变量就是对应于下标为k的节点的父节点。<br>
弄清楚了这个用数组表示的二叉树,就可以理解上面的代码中while循环进行的工作是,<br>
当欲加入的元素小于其父节点时,就将两个节点的位置交换。这个算法保证了如果只执行add操作,那么queue这个二叉树是有序的:<br>
该二叉树中的任意一个节点都小于以该节点为根节点的子数中的任意其它节点。这也就保证了queue[0],即队顶元素总是所有元素中最小的。<br>
需要注意的是,这种算法无法保证不同子树上的两个节点之间的大小关系。举例来说,queue[3]一定会小于queue[7],但是未必会小于queue[9],因为queue[9]不在以queue[3]为根节点的子树上。<br>
弄清楚了add的操作,那么当队列中的元素有变化的时候,对应的数组queue又该如何变化呢?察看函数poll(),<br>
最终追中到函数privateEremoveAt(inti),代码如下:<br>
privateEremoveAt(inti){<br>
asserti>=0&&i<size;<br>
modCount++;<br>
ints=--size;<br>
if(s==i)//removedlastelement<br><span style="font-style:normal">queue<wbr>=null;<br>
else{<br>
Emoved=(E)queue[s];<br>
queue[s]=null;<br>
siftDown(i,moved);<br>
if(queue</wbr></span><span style="font-style:normal"><wbr>==moved){<br>
siftUp(i,moved);<br>
if(queue</wbr></span><span style="font-style:normal"><wbr>!=moved)<br>
returnmoved;<br>
}<br>
}<br>
returnnull;<br>
}</wbr></span><br>
这个函数的实现方法是,将队尾元素取出,插入到位置i,替代被删除的元素,然后做相应的调整,保证二叉树的有序,<br>
即任意节点都是以它为根节点的子树中的最小节点。进一步的代码就留给有兴趣的读者自行分析,<br>
要说明的是,对于queue这样的二叉树结构有一个特性,即如果数组的长度为length,<br>
那么所有下标大于length/2的节点都是叶子节点,其它的节点都有子节点。<br>
总结:<strong><wbr>可以看到这种算法的实现,充分利用了树结构在搜索操作时的优势,效率又高于维护一个全部有序的队列</wbr></strong><wbr>。</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
分享到:
相关推荐
而"pradeepr-roboticist-PriorityQueue-MEX-Matlab-1f6c329"可能是项目仓库的一个特定版本,由作者pradeepr-roboticist维护,版本号为1f6c329,这通常是Git版本控制系统中的一个提交ID,代表了该项目在某一时刻的源...
### Java中的PriorityQueue详解 #### 类概述 `PriorityQueue`是Java集合框架的一部分,它是一个基于优先级堆的无界优先级队列。这个队列的元素可以按照它们的自然顺序或者是通过构造队列时提供的`Comparator`进行...
在Java编程中,优先队列(PriorityQueue)是一种特殊的队列,它按照元素的优先级进行出队。这种数据结构在实现多路归并排序(Multi-Merge Sort)时非常有用,因为它能有效地处理多个已排序的输入流,并将它们合并成...
优先级队列头文件priorityqueue.h
Java的优先队列(PriorityQueue)是Java集合框架中一个重要的数据结构,它是一个基于堆实现的无界队列。优先队列中的元素按照优先级排序,最高的优先级元素总是在队列的头部。在Java中,PriorityQueue类位于`java....
**PriorityQueue带优先级的队列** `PriorityQueue`是Java集合框架中的一种特殊队列,它基于优先堆实现,可以自动对队列中的元素进行排序。与普通队列不同,`PriorityQueue`不是先进先出(FIFO)的数据结构,而是...
优先队列(PriorityQueue)是数据结构中的一种特殊类型,它在处理元素的插入和删除时,不遵循传统的先进先出(FIFO)或后进先出(LIFO)原则,而是根据元素的优先级来决定操作顺序。在许多算法问题和实际应用中,...
PriorityQueue是Java中的一个优先级队列,它可以根据元素的优先级对元素进行排序,并且允许高效地获取和删除最高优先级的元素。
PriorityQueue<Integer> queue = new PriorityQueue(new Comparator() { @Override public int compare(Integer o1, Integer o2) { return o1.compareTo(o2) * -1; // 将默认升序改为降序 } }); ``` 在`...
优先队列(PriorityQueue)是Java集合框架中的一个重要组件,它提供了一种高效处理具有优先级的数据结构。在Java中,PriorityQueue类实现了Queue接口,它遵循最小堆的原理,即队首元素总是队中最小的(默认情况下)...
Java 的优先队列 PriorityQueue 原理及实例分析 Java 的优先队列 PriorityQueue 是 Queue 接口的实现,可以对其中元素进行排序,可以放基本数据类型的包装类(如:Integer,Long 等)或自定义的类。PriorityQueue ...
Java中的PriorityQueue是一种特殊的队列,它遵循优先级原则,即队列中的元素根据其优先级进行排列。PriorityQueue在JDK中内置,基于二叉堆数据结构实现,特别是最小堆,这意味着队列头部的元素总是具有最低的优先级...
JDK源码之PriorityQueue解析 一、优先队列的应用 优先队列是程序开发中常用的数据结构之一。它可以应用于多个领域,如操作系统的进程调度、爬虫系统的任务调度等。在这些应用中,优先队列可以确保高优先级的任务或...
优先级队列cpp文件PriorityQueue.cpp
PriorityQueue 优先队列实现C# PriorityQueueLib: 基于二进制堆的最小/最大优先级队列实现PriorityQueueTests: PriorityQueue单元测试
PriorityQueue PriorityQueue是最小/最大PriorityQueue的Javascript实现。 近期变动 V1.0 在1.0版中,删除了对setComparator(func)和setEquals(func)的支持。 这些方法导致了意外的行为。 需要这些功能时,请...
优先队列PriorityQueue,_堆Heap【数据结构和算法入门8】
在Java编程语言中,`Lists`, `Stack`, `Queue`, 和 `PriorityQueue` 是四个重要的数据结构,它们各自在不同的场景下发挥着关键作用。这些数据结构是Java集合框架的一部分,帮助开发者有效地组织和操作数据。 1. **...
`android-priorityqueue`是一个专门为Android设计的轻量级库,它提供了一个简单且干净的解决方案来处理待办事项(To-Do)列表,使得任务按照优先级进行排序和处理。这个库的核心理念是帮助开发者快速实现具有优先级...
Keap是一种特殊的堆数据结构,它的设计目标是提供稳定的优先级队列(PriorityQueue)功能以及稳定的Keapsort排序算法。在计算机科学中,堆通常用于实现高效的数据操作,如查找最大或最小元素、优先级调度等。Keap堆...