优先级队列:返回最高优先级对象、添加新的对象
堆:将一个给定的集合或数组里面的元素按照完全二叉树层序遍历的顺序存储在一个一维数组中
堆的存储方式:大根堆、小根堆
大根堆:每个节点都大于左右子节点
小根堆:每个节点都小于左右子节点
一.模拟实现堆的创建:
思路:利用数组或集合创建——堆的向下调整
1.从最后一颗子树开始调整
2.每颗子树调整的时候都是向下调整
主要解决问题:
(1)确定最后一课子树的根节点p = [(len-1)-1]/2
(2)p--
(3)堆向下调整,确保左右子节点 主函数里面实现一下 结果 实现向堆中插入元素 思路: 主函数里面实现一下 结果 删除堆中的元素(一定是删除堆顶元素) 结果 获取堆顶元素 模拟实现优先级队列 堆的应用 1.用堆实现优先级队列 2.堆排序 二:优先级队列 优先级队列按照优先级来处理,先出优先级高的元素,要选出优先级最高的元素要借助堆来完成。优先级队列中的添加数据(offer())操作,对应着堆中的添加函数,优先级队列中的删除数据(poll())操作,对应着堆中的删除函数。优先级队列就是将堆进行一次封装,调用堆中的函数。 java集合框架中提供了PriorityQueue和PriorityBlockingQueue两种类型的优先级队列,PriorityQueue是线程不安全的,PriorityBlockingQueue是线程安全的。 1.系统提供给我们优先级队列PriorityQueue中一些常用方法 2.注意: 使用PriorityQueue的一些注意事项 1.使用时必须导入PriorityQueue所在的包,即import java.util.PriorityQueue; 2.PriorityQueue中放置的元素必须能够比较大小,不能插入无法比较大小的对象,否者会抛出类型转换异常 上面的代码看是没有问题,但是当再创建一个新对象时就会报类型转换异常 为什么会出现这样的原因,这就要看PriorityQueue中的offer底层源码了 (1).在offer源码中,有一个向上调整的代码。当i==0时,不会进入该代码,也就是说第一次添加数据不会进行向上调整。 (2).当i!=0,就会进入向上调整代码,追进去可以看到有两个方法。看第二个 (3).向上调整比较,追进去 可以看到它的底层是通过比较器来实现数据的向上调整的。而在写Dog类的时候并没有实现Comparable接口,这里也就无法强转。所以在向优先级队列中插入数据的时候就会报类型转化异常。 解决办法就是在Dog类里面重写 Comparable接口 结果 3.不能插入null对象,否者会抛出空指针异常 4.我们知道优先级队列里面是默认以小堆的方式来排序的,但通过上面的知识我们知道,只要实现Comparable接口重写comparaTo方法即可实现以大堆的方式来排序 下面我们改变整数的排序方式 结果: 3.优先级队列常用的构造方法 4.优先级队列的应用 top-k问题:最大或最小的前k个数据 力扣 力扣import java.util.Arrays;
public class MyPriorityQueue {
public int[] elem;
public int usedsize;
public MyPriorityQueue(){//这里在初始化的时候不要形参
this.elem = new int[10];
}
public boolean justFull(){
return usedsize== elem.length;
}
//创建大根堆
public int[] createBigHeap(int[] array){
int temp = usedsize;
usedsize = 0;
for (int i = 0; i < array.length; i++) {//完成对堆中数据的初始化
if(justFull()){//判断堆是否满,满了就扩容
elem = Arrays.copyOf(elem,2*elem.length);
}
elem[i] = array[i];
usedsize++;
if(usedsize==temp)break;
}
for(int p = (usedsize-1-1)/2;p>=0;p--){//完成堆的向下调整
shiftDown1(p,usedsize);
}
return this.elem;
}
private void shiftDown1(int root,int len){
int parent = root;
int child = 2*parent+1;
while(child
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
MyPriorityQueue heap = new MyPriorityQueue();
int[] elem = new int[]{10,2,1,4,7,3,5,15,11};
System.out.println("创建的大根堆为:");//创建大根堆
heap.createBigHeap(elem);
heap.printHeap();
System.out.println();
System.out.println("=====================");
System.out.println("创建的小根堆为:");//创建小跟堆
heap.createSmallHeap(elem);
heap.printHeap();
System.out.println();
System.out.println("=====================");
}
}
* 将插入的数据放在最后一个节点的后面,然后将插入的节点向上调整直到满足堆的性质
* 1.先判断堆是否满,满了就扩容
* 2.找到最后一个孩子,将新插入的节点放在最后一个孩子后面
* 3.向上调整
public int[] insertHeap(int data){
if(justFull()){//判断堆是否满,满了就扩容
elem = Arrays.copyOf(elem,2*elem.length);
}
elem[usedsize] = data;
int child = usedsize;
usedsize++;
int parent = (child-1)/2;
while(parent>=0){
if(elem[child]>elem[parent]){
int temp = elem[child];
elem[child] = elem[parent];
elem[parent] = temp;
child = parent;
parent = (child-1)/2;
}else{
break;
}
}
return this.elem;
}
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
MyPriorityQueue heap = new MyPriorityQueue();
int[] elem = new int[]{10,2,1,4,7,3,5,15,11};
System.out.println("创建的大根堆为:");//创建大根堆
heap.createBigHeap(elem);
heap.printHeap();
System.out.println();
System.out.println("=====================");
System.out.println("创建的小根堆为:");//创建小跟堆
heap.createSmallHeap(elem);
heap.printHeap();
System.out.println();
System.out.println("=====================");
System.out.println("向堆中插入数据并用大堆创建");
heap.createBigHeap(heap.insertHeap(100));
heap.printHeap();
System.out.println();
}
}
* 堆元素的删除(删除的一定是优先级高的元素):
* 1.将堆顶元素与堆中最后一个元素交换
* 2.将堆中的元素个数减少一个
* 3.将堆顶元素进行向下调整
public int[] deleteHeap(){
if(isEmpty()){//先判断堆中是否有元素,没有就返回
return elem;
}
int parent = 0;
int child = 2*parent+1;
int temp0 = elem[0];
elem[0] = elem[usedsize-1];
elem[usedsize-1] = temp0;
shiftDown2(0,--usedsize);
return elem;
}
public int getHeaphead(){
if(isEmpty()){
System.out.println("优先级队列为空");
return -1;
}
return elem[0];
}
package MyPriorityQueue;
import java.util.AbstractQueue;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
public class MyPriorityQueue
import java.util.Comparator;
public class Test {
public static void main(String[] args) {
MyPriorityQueue
boolean offer(E e) 插入元素e,成功返回true,如果插入null返回空指针异常
peek() 获取优先级最高的元素,如果优先级队列为空,返回null
poll() 移除优先级最高的元素并返回,如果优先级队列为空,返回null
size() 获取有效元素的个数
isEmpty() 检测优先级队列是否为空,空返回true
import java.util.PriorityQueue;
class Dog{
private int age;
public Dog(int age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"age=" + age +
'}';
}
}
public class SystemPriorityQueue {
public static void main(String[] args) {
PriorityQueue
import java.util.PriorityQueue;
class Dog{
private int age;
public Dog(int age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"age=" + age +
'}';
}
}
public class SystemPriorityQueue {
public static void main(String[] args) {
PriorityQueue
import java.util.PriorityQueue;
class Dog implements Comparable
方法一:
public class SystemPriorityQueue {
public static void main(String[] args) {
PriorityQueue
方法二:
class IntCom implements Comparator
PriorityQueue() 创建一个空的优先级队列,默认容量是11
PriorityQueue(int initialCapacity) 创建一个初始容量为initialCapacity的优先级队列,initialCapacity不能小于1,否者会抛出IllegalArgumentException异常
PriorityQueue(Collection extends E> c) 用一个集合来创建优先级队列



