Java PriorityQueue(优先级队列/二叉堆):默认是小顶堆

PriorityQueue

优先队列PriorityQueue是Queue接口的实现,可以对其中元素进行排序,可以放基本数据类型的包装类(如:Integer,Long等)或自定义的类

  • 对于基本数据类型的包装器类,优先队列中元素默认排列顺序是升序排列
  • 对于自己定义的类来说,需要自己定义比较器

    在构造器中可以传入一个比较器

1. 优先队列遍历

PriorityQueue的iterator()不保证以任何特定顺序遍历队列元素。若想按特定顺序遍历,先将队列转成数组,然后排序遍历

2. PriorityQueue有几个需要注意的点:

  • 不允许加入 Null 对象
  • 添加到PriorityQueue的对象必须具有可比性
  • 比较器Comparator可用于队列中对象的自定义排序(升序/降序,自定义参与比较的是对象的哪个变量)
  • PriorityQueue是一个无限制的队列,并且动态增长。默认初始容量’11’可以使用相应构造函数中的initialCapacity参数覆盖
  • 如果存在多个具有相同优先级的对象,则它可以随机轮询其中任何一个
  • PriorityQueue 不是线程安全的。PriorityBlockingQueue在并发环境中使用
  • 它为add/offer和remove/poll方法提供了O(log(n))时间

3. LeetCode 相关习题

23. 合并 K 个升序链表

  • 用容量为K的最小堆优先队列,把链表的头结点都放进去,然后出队当前优先队列中最小的,挂上链表
  • 然后让出队的那个节点的下一个入队,再出队当前优先队列中最小的,直到优先队列为空
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
    	if (lists == null){
    		return null;
		}


		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 dummyNode = new ListNode(-1);
		ListNode cur = dummyNode;	//	指针

		while (!queue.isEmpty()){	//	小顶堆【每次弹出的都是最小的!!!】
			ListNode node1 = queue.poll();
			cur.next = node1;
			if (node1.next != null){
				queue.offer(node1.next);
			}
			cur = cur.next;
		}

		return dummyNode.next;
	}
}

215. 数组中的第 k 个最大元素

第 k 个最大 ===> 有 k - 1 个元素比你小 ===> 构造大小为 k 的小顶堆
当新加入的 > 堆顶

  1. poll
  2. offer(新加入的)
class Solution {
    public int findKthLargest(int[] nums, int k) {
		Queue<Integer> queue = new PriorityQueue<>();	//	维护一个大小为 k 的小顶堆
		for (int i = 0; i < k; i++) {
			queue.add(nums[i]);
		}
		for (int i = k; i < nums.length; i++) {
			if (nums[i] > queue.peek()){
				queue.poll();
				queue.offer(nums[i]);
			}
		}
		return queue.peek();
	}
}

703. 数据流中的第 k 大元素

class KthLargest {
    //  维护一个大小为 k 的小顶堆,新加入一个元素和堆顶比较
    //  1. 如果比堆顶小,丢弃
    //  2. 如果比堆顶大,删除堆顶元素,加入新的 val
    PriorityQueue<Integer> queue;   //  优先级队列
    int size;   //  堆的大小

    public KthLargest(int k, int[] nums) {  //  初始化
        queue = new PriorityQueue<>(k);
        size = k;
        for (int num : nums) {
            add(num);
        }

    }
    
    public int add(int val) {   //  插入数据流 num 后,返回当前数据流中第 k 大的元素
        if (queue.size() < size){   //  优先级队列未满
            queue.offer(val);
        }else {
            if (queue.peek() < val){    //  peek < val,弹出堆顶,压入新值
                queue.poll();
                queue.offer(val);
            }
        }
        return queue.peek();
    }
}
posted @ 2023-08-05 11:30  爱新觉罗LQ  阅读(176)  评论(0编辑  收藏  举报