提前告知:
涉及到最小堆,请看我的另一篇blog:【数据结构】堆 以及 堆排序_向前走-CSDN博客
简单描述
PriorityQueue和Queue的区别在于,它的出队顺序与元素的优先级有关,对PriorityQueue调用remove()或poll()方法,返回的总是优先级最高的元素。
要使用PriorityQueue,我们就必须给每个元素定义“优先级”。
结论:可以通过重写PriorityQueue类中的Comparetor实现控制元素优先级。
通过源码理解
成员变量:
构造器:如果给定了定制排序类Comparator,则使用该类确定元素的优先级,否则使用自然排序类Comparable类确定元素的优先级。
成员方法:
提前告知:主要是,添加元素 和 移除元素。因为底层使用的是最小堆来进行优先队列(底层使用数组实现)中元素的优先级控制,所以添加元素使用的是上浮来调整优先级,移除元素使用的是下沉操作来调整优先级。
添加:
上浮的具体实现:
移除:
综上:
因为重写Comparator接口实现类中的compare(Object o1, Object o2)方法,如果返回值大于0,表示o1大于o2,如果返回值等于0,表示o1等于o2,如果o1小于o2,表示o1小于o2。
不使用Comparator接口实现类,默认使用Conparable接口实现类中的compareTo方法,o1.compareTo(o2),如果返回值大于0,表示o1大于o2,如果返回值等于0,表示o1等于o2,如果o1小于o2,表示o1小于o2。
但是PriorityQueue类中根据最小堆进行排序,所以o1和o2中值小的,优先级越高。
使用实例
来源:合并K个排序链表
使用优先队列合并:
因为有K个链表,而K个链表中每个当前结点都是最小结点,所有通过优先队列存K个结点中的最小值。
代码实现:
使用Comparable接口:
class Solution {
private PriorityQueue<Status> queue = new PriorityQueue<Status>();
class Status implements Comparable<Status>{//创造一个容器实现Comparator接口, 并且按照从小到大的顺序装载数据
private int val;
private ListNode ptr;
public Status(int val, ListNode ptr) {
this.val = val;
this.ptr = ptr;
}
@Override
public int compareTo(Status o2) {
return this.val - o2.val;
}
}
public ListNode mergeKLists(ListNode[] lists) {
ListNode head = new ListNode();
ListNode temp = head;
for(ListNode node : lists) {
if(node != null) {
queue.offer(new Status(node.val, node));
}
}
while(!queue.isEmpty()) {
Status poll = queue.poll();//出队的是某个链表的当前最小值
temp.next = poll.ptr;
temp = temp.next;
if(poll.ptr.next != null) {
queue.offer(new Status(poll.ptr.next.val, poll.ptr.next));
}
}
return head.next;
}
}
使用Comparator接口:
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
PriorityQueue<ListNode> queue = new PriorityQueue<ListNode>(new Comparator<ListNode>() {
@Override
public int compare(ListNode o1, ListNode o2) {
return o1.val - o2.val;
}
});
for(ListNode node : lists) {
if(node != null) {
queue.offer(node);
}
}
ListNode head = new ListNode();
ListNode temp = head;
while(!queue.isEmpty()) {
ListNode minNode = queue.poll();//出队的是某个链表的当前最小值
temp.next = minNode;
temp = temp.next;
if(minNode.next != null) {
queue.offer(minNode.next);
}
}
return head.next;
}
}
其中建造最小堆实现的优先队列时,可以使用lambda表达式:
PriorityQueue<ListNode> queue = new PriorityQueue<ListNode>((o1, o2) -> o1.val - o2.val);