Java优先队列/最小堆(PriorityQueue)讲解

参考文章链接

定义

  • 我们知道队列是遵循先进先出(First-In-First-Out)模式的,但有些时候需要在队列中基于优先级处理对象。举个例子,比方说我们有一个每日交易时段生成股票报告的应用程序,需要处理大量数据并且花费很多处理时间。客户向这个应用程序发送请求时,实际上就进入了队列。我们需要首先处理优先客户再处理普通用户。在这种情况下,Java的PriorityQueue(优先队列)会很有帮助。
  • PriorityQueue类在Java1.5中引入并作为 Java Collections Framework 的一部分。PriorityQueue是基于优先堆的一个无界队列,这个优先队列中的元素可以默认自然排序或者通过提供的Comparator(比较器)在队列实例化的时排序。
  • 优先队列不允许空值,而且不支持non-comparable(不可比较)的对象,比如用户自定义的类。优先队列要求使用Java Comparable和Comparator接口给对象排序,并且在排序时会按照优先级处理其中的元素。
  • 优先队列的头是基于自然排序或者Comparator排序的最小元素。如果有多个对象拥有同样的排序,那么就可能随机地取其中任意一个。当我们获取队列时,返回队列的头对象。
  • 优先队列的大小是不受限制的,但在创建时可以指定初始大小。当我们向优先队列增加元素的时候,队列大小会自动增加。
  • PriorityQueue是非线程安全的,所以Java提供了PriorityBlockingQueue(实现BlockingQueue接口)用于Java多线程环境。
  • 我们有一个用户类,它没有提供任何类型的排序。当我们用它建立优先队列时,应该为其提供一个比较器对象。

实例

我们以一道题为例来解释优先队列的使用。

题目描述

我们有一个由平面上的点组成的列表 points。需要从中找出 K 个距离原点 (0, 0) 最近的点。
(这里,平面上两点之间的距离是欧几里德距离。)
你可以按任何顺序返回答案。除了点坐标的顺序之外,答案确保是唯一的。

实例

实例1

输入:points = [[1,3],[-2,2]], K = 1
输出:[[-2,2]]
解释: 
(1, 3) 和原点之间的距离为 sqrt(10)(-2, 2) 和原点之间的距离为 sqrt(8),
由于 sqrt(8) < sqrt(10)(-2, 2) 离原点更近。
我们只需要距离原点最近的 K = 1 个点,所以答案就是 [[-2,2]]

实例2

输入:points = [[3,3],[5,-1],[-2,4]], K = 2
输出:[[3,3],[-2,4]]
(答案 [[-2,4],[3,3]] 也会被接受。)

思路

维护一个大小为K的优先队列。始终让栈顶为队列中距离远点最大的点。我们要设计一个类,并为其设计一个比较器类。注意比较器里面的compare函数中,要让比较为从大到小。(队列头到队列尾)。

代码

class Solution {
    public int[][] kClosest(int[][] points, int K) {
        //使用K大小的最小堆。(优先队列)
        int [][]ps=new int[K][2];
        PriorityQueue<Point>pq=new PriorityQueue<>(pointComparator);
        for(int i=0;i<points.length;i++)
        {
            pq.add(new Point(points[i][0],points[i][1]));
            if(pq.size()>K){
                pq.poll();
            }
        }
        for(int i=0;i<K;i++)
        {
            Point point=pq.poll();
            ps[i][0]=point.x;
            ps[i][1]=point.y;
        }
        return ps;
    }
     //匿名Comparator实现
    public static Comparator<Point> pointComparator = new Comparator<Point>(){
        //让当前距离最大的在队列,随时准备踢出去。因为队列底要放的是距离最小的
        @Override
        public int compare(Point p1, Point p2) {
            return (int) ((p2.x*p2.x+p2.y*p2.y)-(p1.x*p1.x+p1.y*p1.y));
        }
    };
    class Point{
        int x;
        int y;
        public Point(int x,int y){
            this.x=x;
            this.y=y;
        }
    }
}

这里再贴一些优先队列的常用函数:
在这里插入图片描述
参考链接

发布了55 篇原创文章 · 获赞 28 · 访问量 9265

猜你喜欢

转载自blog.csdn.net/weixin_41796401/article/details/90183114
今日推荐