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

39

优先级队列中的元素可以按照任意的顺序插入,却总是按照排序的顺序进行检索。无论何时调用remove方法,总会获得当前优先级队列中的最小元素,但并不是对所有元素都排序。它是采用了堆(一个可以自我调整的二叉树),执行增加删除操作后,可以让最小元素移动到根。

发表于 2015-12-03 17:06:15

回复(5)

26

PriorityQueue

是从

JDK1.5

开始提供的新的数据结构接口,它是一种基于优先级堆的极大优先级队列。优先级队列是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优先权的元素。如果不提供

Comparator

的话,优先队列中元素默认按自然顺序排列,也就是数字默认是小的在队列头,字符串则按字典序排列(参阅

Comparable

),也可以根据

Comparator

来指定,这取决于使用哪种构造方法。优先级队列不允许

null

元素。依靠自然排序的优先级队列还不允许插入不可比较的对象(这样做可能导致

ClassCastException

)

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

最后,

PriorityQueue

不是线程安全的,入队和出队的时间复杂度是

O(log(n))

发表于 2017-02-26 16:11:57

回复(0)

16

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

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

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

优先级队列的特点 优先级队列里的元素必须有优先级!!!优先级是前后排序的“规则”,也就是说插入队列的类必须实现内部比较器或拥有外部比较器(在构造函数中当参数)!!!!

优先级队列的拥有小根堆的所有特性。

优先级队列不是线程安全的。

优先级队列不允许使用null元素。

优先级队列本身并一个有序(从a[0]-a[n]全部升序)序列,只有当你把元素一个个取出的时候,这些取出的元素所排成的序列才是有序序列。原因很简单,优先级队列是一个小根堆,也就是只能保证根节点(a[0])是最小的,其余元素的顺序不能保证(当然,其他元素必须遵守小根堆的特性),当我们取出元素(poll)时,我们只能取出根节点的元素,然后把堆的最后一个元素剪切到根节点(这种取出方式是底层算法规定的,充分利用了堆的特性),然后对所有剩余元素进行建堆,建堆之后根节点元素还是最小的(初始堆中的第二小)。由此特点,我们可以引出另外两个知识点:①优先级队列的迭代器遍历出来的数组是没有排序的,只是个小根堆。②如果我们想得到有序的堆,需要把堆先转为数组,然后arrays.sort(queue.toarray),arrays.sort(queue.toarray,comparator对象)或者其他sort方法。

优先级队列(堆)中的插入就只能插到最后,也就是说添加和插入一个意思;删除也只能删第一个。

注:每个元素的优先级根据问题的要求而定。当从优先级队列中取出一个元素后,可能出现多个元素具有相同的优先权。在这种情况下,把这些具有相同优先权的元素视为一个先来先服务的队列,按他们的入队顺序进行先后处理。

常用方法:

添加(插入):

publicbooleanadd(E e)

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

publicEpeek()

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

publicEpoll()

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

publicbooleanremove(Object o)

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

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

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

发表于 2018-05-26 16:59:59

回复(2)

3

优先级队列 1.基于优先级堆 2.不允许null值 3.线程不安全 4.出入队时间复杂度O(log(n)) 5.调用remove()返回堆内最小值

编辑于 2019-05-08 10:47:00

回复(0)

3

理解优先队列的概念以及实现就好了(最大堆、最小堆)

两个重要操作:每次插入一个元素、每次返回队列中元素的最值

发表于 2017-08-18 20:09:41

回复(0)

5

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)

1

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)

0

优先队列底层采用小根堆的逻辑结构,动态数组的数据结构。 优先队列的元素必须有优先级,期货的优先级的方式可以实现comparable接口,或通过策略模式引入competitor,因此null元素,进入优先队列中。 在优先队列中元素本身是处于一个无序的状态。因此,通过迭代器进行遍历时优先对列无序的。只有从优先队列中弹出时,才能产生有序的数组。

发表于 2020-12-15 11:26:09

回复(0)

0

优先级队列 1.基于优先级堆 2.不允许null值 3.线程不安全 4.出入队时间复杂度O(log(n)) 5.调用remove()返回堆内最小值

发表于 2020-06-05 01:19:08

回复(0)

0

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

发表于 2020-02-29 21:27:36

回复(0)

0

PriorityQueue是一个基于优先级堆的***队列,它的元素是按照自然顺序(natural order)排序的。在创建的时候,我们可以给它提供一个负责给元素排序的比较器。PriorityQueue不允许null值,因为他们没有自然顺序,或者说他们没有任何的相关联的比较器。最后,PriorityQueue不是线程安全的,入队和出队的时间复杂度是O(log(n))

发表于 2019-04-30 22:25:59

回复(0)

0

PriorityQueue是一个基于优先级堆的***队列,它的元素是按照自然顺序(natural order)排序的。在创建的时候,我们可以给它提供一个负责给元素排序的比较器。PriorityQueue不允许null值,因为他们没有自然顺序,或者说他们没有任何的相关联的比较器。最后,PriorityQueue不是线程安全的,入队和出队的时间复杂度是O(log(n))。

发表于 2019-04-28 16:32:34

回复(0)

0

PriorityQueue是一个基于优先级堆的***队列,它的元素是按照自然顺序(natural order)排序的。在创建的时候,我们可以给它提供一个负责给元素排序的比较器。PriorityQueue不允许null值,因为他们没有自然顺序,或者说他们没有任何的相关联的比较器。最后,PriorityQueue不是线程安全的,入队和出队的时间复杂度是O(log(n))。

发表于 2019-04-27 20:53:28

回复(0)

0

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

发表于 2019-04-26 22:18:02

回复(0)

0

PriorityQueue是一个基于优先级堆的***队列,它的元素是按照自然顺序(natural order)排序的。在创建的时候,我们可以给它提供一个负责给元素排序的比较器。PriorityQueue不允许null值,因为他们没有自然顺序,或者说他们没有任何的相关联的比较器。最后,PriorityQueue不是线程安全的,入队和出队的时间复杂度是O(log(n))。

发表于 2019-04-25 18:36:32

回复(0)

0

PriorityQueue是一个基于优先级堆的***队列,它的元素是按照自然顺序(natural order)排序的。在创建的时候,我们可以给它提供一个负责给元素排序的比较器。PriorityQueue不允许null值,因为他们没有自然顺序,或者说他们没有任何的相关联的比较器。

发表于 2018-09-21 23:10:03

回复(0)

0

PriorityQueue是一个基于优先级堆的***队列,它的元素是按照自然顺序(natural order)排序的。在创建的时候,我们可以给它提供一个负责给元素排序的比较器。PriorityQueue不允许null值,因为他们没有自然顺序,或者说他们没有任何的相关联的比较器。最后,PriorityQueue不是线程安全的,入队和出队的时间复杂度是O(log(n))。

发表于 2018-09-13 11:40:35

回复(0)

0

priorityQuene是一个基于优先级堆的一个***队列,里面的元素是按照自然顺序进行排列,在创建的时候也可以给它提供一个负责元素排序的比较器。它的元素不能为null值,因为这样就没有自然顺序,或者说就是没有一个对应它的比较器。最后,priorityQuene的不是线程安全的,入队和出队的时间复杂度是n(log n)

编辑于 2018-05-03 08:49:34

回复(0)

0

PriorityQueue基于优先级堆得极大优先级队列。若不指定元素的排序方式,则以自然顺序排序,也可实现comparator接口进行自定义排序。队列中不允许有null值,底层是数组,但是可动态改变队列的大小。它是线程不安全的,若用于多线程环境使用PriorityBlockQueue.priorityqueue入队和出队的时间是o(logn).

发表于 2018-03-14 14:30:31

回复(0)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值