目录
目录
3.自定义类型元素间的大小比较 (覆写了equals方法,equals默认是比较地址)
4.比较两个自定义对象谁大谁小(用Comparable接口)
4.有时候要升序、有时候需要降序用java util.Comparator-比较器
1.优先级队列的介绍
优先级队列虽然名字叫队列,但是底层是基于堆的实现,是按照元素间的优先级大小顺序动态(处理的元素个数是动态变化的)出队。
任务管理器就是一个优先级队列。
优先级队列与不同队列的区别
JDK内置的优先级队列默认是最小堆的实现,队首元素就是当前队列的最小值。(所以后面通过比较器把内置最小堆改为了最大堆)
2.优先级队列最大堆的简单实现
覆写了我之前自己写的队列的四个方法,通过自己的实现的二叉堆MaxHeap进行了优先级队列的简单实现。
这个代码执行出来是倒序的一组数字
下面是测试的代码
3.自定义类型元素间的大小比较 (覆写了equals方法,equals默认是比较地址)
传入的o是否是Student类new出来的
if (!(o instanceof Student)) {
return false;
}
比较两个自定义的类型是否相等
public class PriorityQueueTest { public static void main(String[] args) { Student stu1 = new Student("张三", 10); Student stu2 = new Student("李四", 20); Student stu3 = new Student("王淇", 30); System.out.println(stu1.equals(stu3)); } } class Student { String name; int age; public Student(String name, int age) { this.name = name; this.age = age; } // 将当前对象和传入的对象比较 @Override public boolean equals(Object o) { if (o == null) { return false; } if (this == o) { return true; } //传入的o是否是Student类new出来的,如果不是,返回false if (!(o instanceof Student)) { return false; } //向下转型还原为Student类 Student stu = (Student) o; return this.age == stu.age && this.name.equals(stu.name); } @Override public String toString() { return "student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
4.比较两个自定义对象谁大谁小(用Comparable接口)
public class PriorityQueueTest { public static void main(String[] args) { Student stu1 = new Student("张三", 10); Student stu2 = new Student("李四", 20); Student stu3 = new Student("王淇", 5); System.out.println(stu1.compareTo(stu2)); System.out.println(stu2.compareTo(stu3)); } } class Student implements Comparable<Student>{ String name; int age; public Student(String name, int age) { this.name = name; this.age = age; } // 将当前对象和传入的对象比较 @Override public boolean equals(Object o) { if (o == null) { return false; } if (this == o) { return true; } //传入的o是否是Student类new出来的,如果不是,返回false if (!(o instanceof Student)) { return false; } //向下转型还原为Student类 Student stu = (Student) o; return this.age == stu.age && this.name.equals(stu.name); } @Override public String toString() { return "student{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override public int compareTo(Student o) { return this.age-o.age;//被减数和减数反一下就变成了降序排序 } }
然后我把自定义类型的数据放在数组里进行了排序
排序方法默认是升序的,如果要降序,就更改一下CompareTo方法 ,如下,就可降序排序
4.有时候要升序、有时候需要降序用java util.Comparator-比较器
就是创建了基于此接口的俩个类一个升序一个降序
public class PriorityQueueTest { public static void main(String[] args) { Student stu1 = new Student("张三", 40); Student stu2 = new Student("李四", 20); Student stu3 = new Student("王淇", 5); //构造一个对象数组 Student[] students ={stu1,stu2,stu3}; //对数组排序,排序默认是升序 Arrays.sort(students,new StudentComDesc()); System.out.println(Arrays.toString(students)); } } //升序排序 class StudentCom implements Comparator<Student> { @Override public int compare(Student o1, Student o2) { return o1.getAge() - o2.getAge(); } } //降序排序 class StudentComDesc implements Comparator<Student>{ @Override public int compare(Student o1, Student o2) { return o1.getAge()-o2.getAge(); } } class Student { String name; int age; public Student(String name, int age) { this.name = name; this.age = age; } public int getAge() { return age; } // 将当前对象和传入的对象比较 @Override public boolean equals(Object o) { if (o == null) { return false; } if (this == o) { return true; } //传入的o是否是Student类new出来的,如果不是,返回false if (!(o instanceof Student)) { return false; } //向下转型还原为Student类 Student stu = (Student) o; return this.age == stu.age && this.name.equals(stu.name); } @Override public String toString() { return "student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
执行代码的截图
使用Comparator相比Comparable来说更加灵活,无侵入编程(策略模式)
5.用Comparator将JDK的最小堆改造为最大堆使用
第一种写法:
public class PriorityQueueTest { public static void main(String[] args) { //通过构造方法传入比较器 //这是对优先级队列的声明 //默认是最小堆,“值”(比较器Compare的返回值越小,优先级越高) // Queue<Student> queue =new PriorityQueue<>(new StudentCom()); //传入降序比较器时,“值”(比较器Compare的返回值越大,返回复数,优先级越高) // Queue<Student> queue =new PriorityQueue<>(new StudentComDesc()); //第二种写法 /*Queue<Student> queue =new PriorityQueue<>(new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { return o1.getAge() - o2.getAge(); } });*/ //函数式编程 Queue<Student> queue =new PriorityQueue<>((o1,o2) -> o2.getAge()- o1.getAge()); Student stu1 = new Student("张三", 40); Student stu2 = new Student("李四", 20); Student stu3 = new Student("王淇", 18); //入队 queue.offer(stu1); queue.offer(stu2); queue.offer(stu3); System.out.println(queue); while(!queue.isEmpty()){ System.out.println(queue.poll()); } } } //升序排序 class StudentCom implements Comparator<Student> { @Override public int compare(Student o1, Student o2) { return o1.getAge() - o2.getAge(); } } //降序排序 class StudentComDesc implements Comparator<Student>{ @Override public int compare(Student o1, Student o2) { return o2.getAge()-o1.getAge(); } } class Student { String name; int age; public Student(String name, int age) { this.name = name; this.age = age; } public int getAge() { return age; } // 将当前对象和传入的对象比较 @Override public boolean equals(Object o) { if (o == null) { return false; } if (this == o) { return true; } //传入的o是否是Student类new出来的,如果不是,返回false if (!(o instanceof Student)) { return false; } //向下转型还原为Student类 Student stu = (Student) o; return this.age == stu.age && this.name.equals(stu.name); } @Override public String toString() { return "student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
第二种写法:(匿名内部类)
第三种写法:(函数式编程)
了解即可
6.笔试题:最小k个数(非常爱考的问题)
6.1最小k个数
看到找最小或者在最大,都是优先级队列
找最大k的思路: 以找最大的三个数为例:构造只有三个元素的最小堆,最小堆中就存放最大的三个元素
然后把小的换出堆,把大的换进堆中,保留堆中的三个元素
public class Num17_14_SmallestK { public int[] smallest(int[] arr, int k) { if (arr.length == 0 || k == 0) { return new int[0]; } //构造一个最大堆,JDK默认是最小堆,用比较器改造为最大堆 //要把最小堆改为最大堆,就是要告诉编译器值越大,让编译器来看反而小 Queue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o2 - o1; } }); for (int i:arr) { if(queue.size()<k){ queue.offer(i); }else{ //比较当前元素与栈顶元素的大小 //大于堆顶元素,则大于堆中的所有值 int peek = queue.peek(); if(i>peek){ continue; }else{ //小于堆顶元素,出堆顶,入、i queue.poll(); queue.offer(i); } } } int[] ret =new int[k]; for (int i = 0; i < k; i++) { ret[i] =queue.poll(); } return ret; } }
6.2前k个高频元素(这个系列最难的一道题)