[Java基础]PriorityQueue

优先级队列

数据结构是堆

一. PriorityQueue

PriorityQueue 简介

继承关系

PriorityQueue 示例

二. Comparable 比较器

Compare 接口

三. Comparator 比较器

Comparator 接口

四. 底层原理

一. PriorityQueue
PriorityQueue 简介
PriorityQueue ,即优先级队列。优先级队列可以保证每次取出来的元素都是队列中的最小或最大的元素<Java优先级队列默认每次取出来的为最小元素>。

大小关系:元素的比较可以通过元素本身进行自然排序,也可以通过构造方法传入比较器进行比较。

继承关系

通过继承关系图可以知道 PriorityQueue 是 Queue 接口的一个实现类,而 Queue 接口是 Collection 接口的一个实现类,因此其拥有 Collection 接口的基本操作,此外,队列还提供了其他的插入,移除和查询的操作。每个方法存在两种形式:一种是抛出异常(操作失败时),另一种是返回一个特殊值(null 或 false)。

PriorityQueue 的 peek 和 element 操作的时间复杂度都为常数,add,offer,remove 以及 poll 的时间复杂度是 log(n)。

PriorityQueue 示例
impot java.util.PriorityQueue;

public class PriorityQueueTest{
public static void main(String[] args){
PriorityQueue queue = new PriorityQueue<>();
queue.add(11);
queue.add(22);
queue.add(33);
queue.add(55);
queue.add(44);
System.out.println(queue.remove());
System.out.println(queue.remove());
System.out.println(queue.remove());
System.out.println(queue.remove());
System.out.println(queue.remove());
}
}
运行结果:

代码中我们依次添加11,22,33,55,44五个数据,然后进行删除,通过结果我们发现,每次删除的都为队列中最小元素,即体现了优先级队列。

结论:优先级队列默认每次获取队列最小的元素,也可以通过 comparator 比较器来自定义每次获取为最小还是最大。

注意:优先级队列中不可以存储 null。

二. Comparable 比较器
Compare 接口
public interface Comparable{
public int compareTo(T o);
}
该接口只存在一个 public int compareTo(T o); 方法,该方法表示所在的对象和 o 对象进行比较,返回值分三种:

1:表示该对象大于 o 对象
0:表示该对象等于 o 对象
-1:表示该对象小于 o 对象

需求:在优先级队列中存储对象学生,每个学生有 id,name 两个属性,并且使优先级队列每次按照学生的 id 从小到大取出。

代码示例:

Student 类:当前类实现了 Comparable 接口,即当前类提供了默认的比较方法。

public class Student implements Comparable{
    private int id;
    private String name;
    public Student(int id,String name,int age){
        this.id = id;
        this.name = name;
    }
    public int getId(){
        return id;
    }
    @Override
    public String toString(){
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
    @Override
    public int compareTo(Object o){
        Student o1 = (Student)o;
        return this.id - o1.id;
    }
}

PriorityQueueTest 类:

public class PriorityQueueTest {
public static void main(String[] args) {
PriorityQueue queue = new PriorityQueue<>();
queue.add(new Student(2,"Jack"));
queue.add(new Student(1,"Mary"));
queue.add(new Student(5,"Mcan"));
queue.add(new Student(4,"Scolt"));
queue.add(new Student(3,"Tina"));
System.out.println(queue.remove());
System.out.println(queue.remove());
System.out.println(queue.remove());
System.out.println(queue.remove());
System.out.println(queue.remove());
}
}
运行结果:

三. Comparator 比较器
新需求:如果使优先级队列按照学生 id 从大到小取出呢?我们很快就会想到修改 Student 类的compareTo 方法,使 return o1.id - this.id;这样当然可以实现我们的新需求。但是有很多时候类的compareTo 方法是不能修改的,比如 JDK 给我们提供的源代码,在不修改 compareTo 方法的前提下实现需求,只能用 comparator 比较器了。

Comparator 接口
public interface Comparator{
int compare(T o1,T o2);
}
该接口只存在一个 int compare(T o1,T o2);方法,该方法需要参数是两个待比较的对象,返回结果是 int 类型:

1:表示 o1对象 大于 o2 对象
0:表示 o1对象 等于 o2 对象
-1:表示 o1对象 小于 o2 对象

public class PriorityQueueTest {
public static void main(String[] args) {
PriorityQueue queue = new PriorityQueue<>(new Comparator() {

        @Override
        public int compare(Student o1, Student o2) {
            return o2.getId() - o1.getId();
    }
})
queue.add(new Student(2, "Jack"));
queue.add(new Student(1, "Mary"));
queue.add(new Student(5, "Mcan"));
queue.add(new Student(4, "Scolt"));
queue.add(new Student(3, "Tina"));
System.out.println(queue.remove());
System.out.println(queue.remove());
System.out.println(queue.remove());
System.out.println(queue.remove());
System.out.println(queue.remove());

}
}
运行结果:

四. 底层原理
优先级队列是如何保证每次取出的是队列中最小(最大)的元素的呢?查看源代码,底层的存储结构为一个数组

transient Object[] queue;

表面上是一个数组结构,实际上优先队列采用的是堆的形式来进行存储的,通过调整小堆或大堆来保证每次取出的元素为队列中的最小或最大。

作者:Esofar

出处:https://www.cnblogs.com/DCFV/p/18438542

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   Duancf  阅读(96)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
more_horiz
keyboard_arrow_up light_mode palette
选择主题
点击右上角即可分享
微信分享提示