首页 > 试题广场 >

什么是Java优先级队列(Priority Queue)?

[问答题]
什么是Java优先级队列(Priority Queue)?
PriorityQueue是一个基于优先级堆的***队列,它的元素是按照自然顺序(natural order)排序的。在创建的时候,我们可以给它提供一个负责给元素排序的比较器。PriorityQueue不允许null值,因为他们没有自然顺序,或者说他们没有任何的相关联的比较器。最后,PriorityQueue不是线程安全的,入队和出队的时间复杂度是O(log(n))。
发表于 2019-04-27 20:53:28 回复(0)
更多回答
优先级队列中的元素可以按照任意的顺序插入,却总是按照排序的顺序进行检索。无论何时调用remove方法,总会获得当前优先级队列中的最小元素,但并不是对所有元素都排序。它是采用了堆(一个可以自我调整的二叉树),执行增加删除操作后,可以让最小元素移动到根。
发表于 2015-12-03 17:06:15 回复(5)

PriorityQueue 是从 JDK1.5 开始提供的新的数据结构接口,它是一种基于优先级堆的极大优先级队列。优先级队列是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优先权的元素。如果不提供 Comparator 的话,优先队列中元素默认按自然顺序排列,也就是数字默认是小的在队列头,字符串则按字典序排列(参阅 Comparable ),也可以根据 Comparator 来指定,这取决于使用哪种构造方法。优先级队列不允许 null 元素。依靠自然排序的优先级队列还不允许插入不可比较的对象(这样做可能导致 ClassCastException

优先级队列是***的,但是有一个内部容量,控制着用于存储队列元素的数组大小。它通常至少等于队列的大小。随着不断向优先级队列添加元素,其容量会自动增加。无需指定容量增加策略的细节。

最后, PriorityQueue 不是线程安全的,入队和出队的时间复杂度是 O(log(n))

发表于 2017-02-26 16:11:57 回复(0)

注意:这里的优先级队列不是数据结构中的概念,而是java中的集合类。

注意:建议先把我博客里的堆,比较器这两篇文章看一哈


优先级队列的定义

  • 优先级队列是逻辑结构是小根堆,存储结构是动态数组(到达上限,容量自动加一)的集合类。

优先级队列的特点

  • 优先级队列里的元素必须有优先级!!!优先级是前后排序的“规则”,也就是说插入队列的类必须实现内部比较器或拥有外部比较器(在构造函数中当参数)!!!!
  • 优先级队列的拥有小根堆的所有特性。
  • 优先级队列不是线程安全的。
  • 优先级队列不允许使用null元素。
  • 优先级队列本身并一个有序(从a[0]-a[n]全部升序)序列,只有当你把元素一个个取出的时候,这些取出的元素所排成的序列才是有序序列。原因很简单,优先级队列是一个小根堆,也就是只能保证根节点(a[0])是最小的,其余元素的顺序不能保证(当然,其他元素必须遵守小根堆的特性),当我们取出元素(poll)时,我们只能取出根节点的元素,然后把堆的最后一个元素剪切到根节点(这种取出方式是底层算法规定的,充分利用了堆的特性),然后对所有剩余元素进行建堆,建堆之后根节点元素还是最小的(初始堆中的第二小)。由此特点,我们可以引出另外两个知识点:①优先级队列的迭代器遍历出来的数组是没有排序的,只是个小根堆。②如果我们想得到有序的堆,需要把堆先转为数组,然后arrays.sort(queue.toarray),arrays.sort(queue.toarray,comparator对象)或者其他sort方法。
  • 优先级队列(堆)中的插入就只能插到最后,也就是说添加和插入一个意思;删除也只能删第一个。
  • 注:每个元素的优先级根据问题的要求而定。当从优先级队列中取出一个元素后,可能出现多个元素具有相同的优先权。在这种情况下,把这些具有相同优先权的元素视为一个先来先服务的队列,按他们的入队顺序进行先后处理。

常用方法:

添加(插入):

public boolean add(E e)

查看(只返回根节点元素,不删除):

public E peek()

取出(返回根节点元素,会删除源数据):

public E poll()

删除(如果有多个相同元素,只会删除第一个):

public boolean remove(Object o)

还有就是一些collection类通有的方法,不多说了

记住!!!所有会破坏堆的特性的方法(比如插入删除等)的源码里最后都会加一个建堆方法(siftUp(i, e),也可以说交换方法,调整方法),使队列保持堆的特性


感谢几位大佬,想了解更多源码,例子,实例图的可以去看看:

https://www.cnblogs.com/demingblog/p/6485193.html

https://www.cnblogs.com/CarpenterLee/p/5488070.html

https://blog.csdn.net/u013309870/article/details/71189189

https://blog.csdn.net/cainv89/article/details/51588920

发表于 2018-05-26 16:59:59 回复(2)
优先级队列 1.基于优先级堆 2.不允许null值 3.线程不安全 4.出入队时间复杂度O(log(n)) 5.调用remove()返回堆内最小值
编辑于 2019-05-08 10:47:00 回复(0)
理解优先队列的概念以及实现就好了(最大堆、最小堆)
两个重要操作:每次插入一个元素、每次返回队列中元素的最值

发表于 2017-08-18 20:09:41 回复(0)
PriorityQueue是个基于优先级堆的极大优先级队列。
此队列按照在构造时所指定的顺序对元素排序,既可以根据元素的自然顺序来指定排序(参阅 Comparable),
也可以根据 Comparator 来指定,这取决于使用哪种构造方法。优先级队列不允许 null 元素。
依靠自然排序的优先级队列还不允许插入不可比较的对象(这样做可能导致 ClassCastException)

队列检索操作 poll、remove、peek 和 element 访问处于队列头的元素。
优先级队列是***的,但是有一个内部容量,控制着用于存储队列元素的数组的大小。
它总是至少与队列的大小相同。随着不断向优先级队列添加元素,其容量会自动增加。无需指定容量增加策略的细节。
注意1:该队列是用数组实现,但是数组大小可以动态增加,容量无限。
注意2:此实现不是同步的。不是线程安全的。如果多个线程中的任意线程从结构上修改了列表, 则这些线程不应同时访问 PriorityQueue 实例,这时请使用线程安全的PriorityBlockingQueue 类。
注意3:不允许使用 null 元素。
注意4:此实现为插入方法(offer、poll、remove() 和 add 方法)提供 O(log(n)) 时间;
为 remove(Object) 和 contains(Object) 方法提供线性时间;
为检索方法(peek、element 和 size)提供固定时间。
注意5:方法iterator()中提供的迭代器并不保证以有序的方式遍历优先级队列中的元素。
至于原因可参考下面关于PriorityQueue的内部实现
如果需要按顺序遍历,请考虑使用 Arrays.sort(pq.toArray())。
注意6:可以在构造函数中指定如何排序。如:
PriorityQueue()
使用默认的初始容量(11)创建一个 PriorityQueue,并根据其自然顺序来排序其元素(使用 Comparable)。
PriorityQueue(int initialCapacity)
使用指定的初始容量创建一个 PriorityQueue,并根据其自然顺序来排序其元素(使用 Comparable)。
PriorityQueue(int initialCapacity, Comparator comparator)
使用指定的初始容量创建一个 PriorityQueue,并根据指定的比较器comparator来排序其元素。
注意7:此类及其迭代器实现了 Collection 和 Iterator 接口的所有可选 方法。
PriorityQueue的内部实现
PriorityQueue对元素采用的是堆排序,头是按指定排序方式的最小元素。堆排序只能保证根是最大(最小),整个堆并不是有序的。
方法iterator()中提供的迭代器可能只是对整个数组的依次遍历。也就只能保证数组的第一个元素是最小的。
发表于 2017-03-27 14:20:21 回复(0)
PriorityQueue会对入队的元素进行排序,所以在队列顶端的总是最小的元素,但是队列中不是所有元素都是有序的。这个是根据下面的函数有关的
private void siftUpComparable(int k, E x) {
        Comparable<? super E> key = (Comparable<? super E>) x;
        while (k > 0) {
            int parent = (k - 1) >>> 1;
            Object e = queue[parent];
            if (key.compareTo((E) e) >= 0)
                break;
            queue[k] = e;
            k = parent;
        }
        queue[k] = key;
    }
每次元素插入的位置(为k),就是队列的下标,根据下标找到父节点进行比较,如此循环,直到保证根节点最小就行,所以队列中不是所有的
元素都是有序的。例如:d,a,f,e,b入列后对应的queue[0] = a、queue[1] = b、queue[2] = f、queue[3] = e、queue[4] = d。
发表于 2017-06-09 16:44:59 回复(0)
注意:这里的优先级队列不是数据结构中的概念,而是java中的集合类。 注意:建议先把我博客里的堆,比较器这两篇文章看一哈 优先级队列的定义 优先级队列是逻辑结构是小根堆,存储结构是动态数组(到达上限,容量自动加一)的集合类。 优先级队列的特点 优先级队列里的元素必须有优先级!!!优先级是前后排序的“规则”,也就是说插入队列的类必须实现内部比较器或拥有外部比较器(在构造函数中当参数)!!!! 优先级队列的拥有小根堆的所有特性。 优先级队列不是线程安全的。 优先级队列不允许使用null元素。 优先级队列本身并一个有序(从a[0]-a[n]全部升序)序列,只有当你把元素一个个取出的时候,这些取出的元素所排成的序列才是有序序列。原因很简单,优先级队列是一个小根堆,也就是只能保证根节点(a[0])是最小的,其余元素的顺序不能保证(当然,其他元素必须遵守小根堆的特性),当我们取出元素(poll)时,我们只能取出根节点的元素,然后把堆的最后一个元素剪切到根节点(这种取出方式是底层算法规定的,充分利用了堆的特性),然后对所有剩余元素进行建堆,建堆之后根节点元素还是最小的(初始堆中的第二小)。由此特点,我们可以引出另外两个知识点:①优先级队列的迭代器遍历出来的数组是没有排序的,只是个小根堆。②如果我们想得到有序的堆,需要把堆先转为数组,然后arrays.sort(queue.toarray),arrays.sort(queue.toarray,comparator对象)或者其他sort方法。 优先级队列(堆)中的插入就只能插到最后,也就是说添加和插入一个意思;删除也只能删第一个。 注:每个元素的优先级根据问题的要求而定。当从优先级队列中取出一个元素后,可能出现多个元素具有相同的优先权。在这种情况下,把这些具有相同优先权的元素视为一个先来先服务的队列,按他们的入队顺序进行先后处理。 常用方法: 添加(插入): public boolean add(E e) 查看(只返回根节点元素,不删除): public E peek() 取出(返回根节点元素,会删除源数据): public E poll() 删除(如果有多个相同元素,只会删除第一个): public boolean remove(Object o) 还有就是一些collection类通有的方法,不多说了 记住!!!所有会破坏堆的特性的方法(比如插入删除等)的源码里最后都会加一个建堆方法(siftUp(i, e),也可以说交换方法,调整方法),使队列保持堆的特性 感谢几位大佬,想了解更多源码,例子,实例图的可以去看看: https://www.cnblogs.com/demingblog/p/6485193.html https://www.cnblogs.com/CarpenterLee/p/5488070.html https://blog.csdn.net/u013309870/article/details/71189189 https://blog.csdn.net/cainv89/article/details/51588920
发表于 2021-08-14 00:52:20 回复(0)
优先队列底层采用小根堆的逻辑结构,动态数组的数据结构。 优先队列的元素必须有优先级,期货的优先级的方式可以实现comparable接口,或通过策略模式引入competitor,因此null元素,进入优先队列中。 在优先队列中元素本身是处于一个无序的状态。因此,通过迭代器进行遍历时优先对列无序的。只有从优先队列中弹出时,才能产生有序的数组。
发表于 2020-12-15 11:26:09 回复(0)
优先级队列 1.基于优先级堆 2.不允许null值 3.线程不安全 4.出入队时间复杂度O(log(n)) 5.调用remove()返回堆内最小值
发表于 2020-06-05 01:19:08 回复(0)

是一个基于优先级堆的队列,存储的元素必须可比较的。非线性安全,时间复杂度为log(n)

发表于 2020-02-29 21:27:36 回复(0)
PriorityQueue是一个基于优先级堆的***队列,它的元素是按照自然顺序(natural order)排序的。在创建的时候,我们可以给它提供一个负责给元素排序的比较器。PriorityQueue不允许null值,因为他们没有自然顺序,或者说他们没有任何的相关联的比较器。最后,PriorityQueue不是线程安全的,入队和出队的时间复杂度是O(log(n))
发表于 2019-04-30 22:25:59 回复(0)
PriorityQueue是一个基于优先级堆的***队列,它的元素是按照自然顺序(natural order)排序的。在创建的时候,我们可以给它提供一个负责给元素排序的比较器。PriorityQueue不允许null值,因为他们没有自然顺序,或者说他们没有任何的相关联的比较器。最后,PriorityQueue不是线程安全的,入队和出队的时间复杂度是O(log(n))。
发表于 2019-04-28 16:32:34 回复(0)

priortyQueue是一个基于优先级堆的***队列 元素是按自然顺序排序的 不允许null值 他不是线程安全

发表于 2019-04-26 22:18:02 回复(0)
PriorityQueue是一个基于优先级堆的***队列,它的元素是按照自然顺序(natural order)排序的。在创建的时候,我们可以给它提供一个负责给元素排序的比较器。PriorityQueue不允许null值,因为他们没有自然顺序,或者说他们没有任何的相关联的比较器。最后,PriorityQueue不是线程安全的,入队和出队的时间复杂度是O(log(n))。
发表于 2019-04-25 18:36:32 回复(0)
PriorityQueue是一个基于优先级堆的***队列,它的元素是按照自然顺序(natural order)排序的。在创建的时候,我们可以给它提供一个负责给元素排序的比较器。PriorityQueue不允许null值,因为他们没有自然顺序,或者说他们没有任何的相关联的比较器。
发表于 2018-09-21 23:10:03 回复(0)
PriorityQueue是一个基于优先级堆的***队列,它的元素是按照自然顺序(natural order)排序的。在创建的时候,我们可以给它提供一个负责给元素排序的比较器。PriorityQueue不允许null值,因为他们没有自然顺序,或者说他们没有任何的相关联的比较器。最后,PriorityQueue不是线程安全的,入队和出队的时间复杂度是O(log(n))。
发表于 2018-09-13 11:40:35 回复(0)
priorityQuene是一个基于优先级堆的一个***队列,里面的元素是按照自然顺序进行排列,在创建的时候也可以给它提供一个负责元素排序的比较器。它的元素不能为null值,因为这样就没有自然顺序,或者说就是没有一个对应它的比较器。最后,priorityQuene的不是线程安全的,入队和出队的时间复杂度是n(log n)
编辑于 2018-05-03 08:49:34 回复(0)
PriorityQueue基于优先级堆得极大优先级队列。若不指定元素的排序方式,则以自然顺序排序,也可实现comparator接口进行自定义排序。队列中不允许有null值,底层是数组,但是可动态改变队列的大小。它是线程不安全的,若用于多线程环境使用PriorityBlockQueue.priorityqueue入队和出队的时间是o(logn).
发表于 2018-03-14 14:30:31 回复(0)