目录
一、优先队列概述
简介:
优先队列PriorityQueue是Queue接口的实现,可以对其中元素进行排序,可以放基本数据类型的包装类(如:Integer,Long等)或自定义的类。对于基本数据类型的包装器类,优先队列中元素默认排列顺序是升序排列,但对于自己定义的类来说,需要自己定义比较器
API描述:
基于优先级堆的无限优先级queue 。 优先级队列的元素根据它们的有序natural ordering ,或由一个Comparator
在队列构造的时候提供,这取决于所使用的构造方法。 优先队列不允许null
元素。 依靠自然排序的优先级队列也不允许插入不可比较的对象(这样做可能导致ClassCastException
)。
该队列的头部是相对于指定顺序的最小元素。 如果多个元素被绑定到最小值,那么头就是这些元素之一 - 关系被任意破坏。 队列检索操作poll
, remove
, peek
和element
访问在队列的头部的元件。
类及其迭代器实现Collection
和Iterator
接口的所有可选方法。 方法iterator()
中提供的迭代器不能保证以任何特定顺序遍历优先级队列的元素。 如果需要有序遍历,请考虑使用Arrays.sort(pq.toArray())
。
请注意,此实现不同步。 如果任何线程修改队列,多线程不应同时访问PriorityQueue
实例。 而是使用线程安全的PriorityBlockingQueue
类。
实现注意事项:此实现提供了O(日志(n))的时间入队和出队方法( offer
, poll
, remove()
和add
); remove(Object)
和contains(Object)
方法的线性时间; 和恒定时间检索方法( peek
, element
和size
)。
二、常用方法
以下基于JDK1.8版本,不同版本的JDK中方法略有不同,这个PriorityQueue自1.5开始,
详情可自行查看官方API。
构造方法:
|
|
|
|
|
|
|
方法摘要:
Modifier and Type | Method and Description |
---|---|
boolean |
add(E e) 将指定的元素插入到此优先级队列中。 |
void |
clear() 从此优先级队列中删除所有元素。 |
Comparator<? super E> |
comparator() 返回用于为了在这个队列中的元素,或比较 |
boolean |
contains(Object o) 如果此队列包含指定的元素,则返回 |
Iterator<E> |
iterator() 返回此队列中的元素的迭代器。 |
boolean |
offer(E e) 将指定的元素插入到此优先级队列中。 |
E |
peek() 检索但不删除此队列的头,如果此队列为空,则返回 |
E |
poll() 检索并删除此队列的头,如果此队列为空,则返回 |
boolean |
remove(Object o) 从该队列中删除指定元素的单个实例(如果存在)。 |
int |
size() 返回此集合中的元素数。 |
Spliterator<E> |
spliterator() 在此队列中的元素上创建late-binding和失败快速 |
Object[] |
toArray() 返回一个包含此队列中所有元素的数组。 元素没有特定的顺序。 返回的数组将是“安全的”,因为该队列不保留对它的引用。 (换句话说,这个方法必须分配一个新的数组)。 因此,调用者可以自由地修改返回的数组。 此方法充当基于阵列和基于集合的API之间的桥梁。 |
<T> T[] |
toArray(T[] a) 返回一个包含此队列中所有元素的数组; 返回的数组的运行时类型是指定数组的运行时类型。 |
三、优先队列的使用
1.队列保存的是基本数据类型的包装类
//自定义比较器,降序排列
static Comparator<Integer> cmp = new Comparator<Integer>() {
public int compare(Integer e1, Integer e2) {
return e2 - e1; //降序
}
};
public static void main(String[] args) {
//不用比较器,默认升序排列
Queue<Integer> q = new PriorityQueue<>();
q.add(8);
q.add(5);
q.add(13);
q.add(2);
System.out.println("**********不使用比较器********************");
while(!q.isEmpty())
{
System.out.print(q.poll()+" ");
}
System.out.println();
System.out.println("**********使用比较器********************");
//使用自定义比较器,降序排列
Queue qq = new PriorityQueue(cmp);
qq.add(8);
qq.add(5);
qq.add(13);
qq.add(2);
while(!qq.isEmpty())
{
System.out.print(qq.poll()+" ");
}
}
结果:
**********不使用比较器********************
2 5 8 13
**********使用比较器********************
13 8 5 2
2.队列保存的是自定义类
//自定义比较类,先比较长,长升序排列,若长相等再比较宽,宽降序
static Comparator<Node> cNode=new Comparator<Node>() {
public int compare(Node o1, Node o2) {
if(o1.chang!=o2.chang)
return o1.chang-o2.chang;
else
return o2.kuan-o1.kuan;
}
};
public static void main(String[] args) {
Queue<Node> q=new PriorityQueue<>(cNode);
Node n1=new Node(1, 2);
Node n2=new Node(2, 5);
Node n3=new Node(2, 3);
Node n4=new Node(1, 2);
q.add(n1);
q.add(n2);
q.add(n3);
Node n;
while(!q.isEmpty())
{
n=q.poll();
System.out.println("长: "+n.chang+" 宽:" +n.kuan);
}
}
结果:
长: 1 宽:2
长: 2 宽:5
长: 2 宽:3
3.优先队列遍历
PriorityQueue的iterator()不保证以任何特定顺序遍历队列元素。
若想按特定顺序遍历,先将队列转成数组,然后排序遍历
示例
Queue<Integer> q = new PriorityQueue<>(cmp);
int[] nums= {2,5,3,4,1,6};
for(int i:nums)
{
q.add(i);
}
Object[] nn=q.toArray();
Arrays.sort(nn);
for(int i=nn.length-1;i>=0;i--)
System.out.print((int)nn[i]+" ");
/**
* 输出结果
* 6 5 4 3 2 1
*/
4.比较器生降序说明
Comparator<Object> cmp = new Comparator<Object>() {
public int compare(Object o1, Object o2) {
//升序
return o1-o2;
//降序
return o2-o1;
}
};