java中PriorityQueue优先队列
 优先队列 :底层是用数组实现的二叉堆,因为堆通常分为大顶堆或者小顶堆,所以优先队列可以获取每次出来的都是最大或者最小元素(对象可以实现比较器,Java优先级队列默认每次取出来的为最小元素)。
 因为底层实现是数据结构堆,所以其时间复杂度peek和element操作的时间复杂度都为常数,
 add、offer、remove以及poll的时间复杂度是log(n)。
底层原理:
优先队列底层实际是用数组实现的二叉堆
 优先级队列表示为一个平衡的二进制堆:队列[n]的两个子队列是队列[2n+1]和队列[2(n+1)]。优先级队列根据比较器排序,或者如果比较器为空,则根据元素的自然顺序排序:
 
 对于堆的实现是基于数组来实现的,实际开辟存储空间是数组,对数据的访问按照二叉树来进行访问遍历。父节点和子节点编号存在联系,父节点和子节点存在如下关系:
 Arr[(i-1)/2] Returns the parent node
 Arr[(2i)+1] Returns the left child node
 Arr[(2i)+2] Returns the right child node
 以小根堆为例,数据如何进行调整:
 插入数据
 入数据首先在有效数据的最后一个位置,即插入在某个叶子节点上,以该节点为待调整节点,和其父节点比较,如果当前节点大于父节点,符合小根堆,不用进行调整,否则需要进行调整,调整至0号根节点或者是其中某一个位置时当前节点大于父节点才终止。

 源码:
public boolean offer(E e) {
    if (e == null)
        throw new NullPointerException();
    modCount++;
    int i = size;
    if (i >= queue.length)
        grow(i + 1);
    size = i + 1;
    if (i == 0)
        queue[0] = e;
    else
        siftUp(i, e);
    return true;
}
private void siftUp(int k, E x) {
    if (comparator != null)
        siftUpUsingComparator(k, x);
    else
        siftUpComparable(k, x);
}
@SuppressWarnings("unchecked")
private void siftUpComparable(int k, E x) {
    Comparable<? super E> key = (Comparable<? super E>) x;
    while (k > 0) {
        int parent = (k - 1) >>> 1;
        Object e = queue[parent];
        if (key.compareTo((E) e) >= 0)
            break;
        queue[k] = e;
        k = parent;
    }
    queue[k] = key;
}
 
删除数据
 因为是小根堆,其堆顶元素最小,所以删除的为堆顶的元素。删除堆顶元素过程,首先记录0号下标的位置,并用最后一个元素替换0号下标的元素,当前的小根堆可能被破坏,需要对堆进行调整,从k指定的位置开始,将逐层向下与当前的左右孩子中较小的进行交换,直到x小于或者等于左右孩子中的任何一个为止。
 源码

public E poll() {
    if (size == 0)
        return null;
    int s = --size;
    modCount++;
    E result = (E) queue[0];
    E x = (E) queue[s];
    queue[s] = null;
    if (s != 0)
        siftDown(0, x);
    return result;
}
private void siftDown(int k, E x) {
    if (comparator != null)
        siftDownUsingComparator(k, x);
    else
        siftDownComparable(k, x);
}
@SuppressWarnings("unchecked")
private void siftDownComparable(int k, E x) {
    Comparable<? super E> key = (Comparable<? super E>)x;
    int half = size >>> 1;        // loop while a non-leaf
    while (k < half) {
        int child = (k << 1) + 1; // assume left child is least
        Object c = queue[child];
        int right = child + 1;
        if (right < size &&
            ((Comparable<? super E>) c).compareTo((E) queue[right]) > 0)
            c = queue[child = right];
        if (key.compareTo((E) c) <= 0)
            break;
        queue[k] = c;
        k = child;
    }
    queue[k] = key;
}
 
应用
集合排序
```java
package com.example.demo.suanfa.binary.heap;
import java.util.PriorityQueue;
import java.util.Queue;
public class HeapTest {
    public static void main(String[] args) {
        Queue<Integer> queue = new PriorityQueue<>();
        queue.add(2);
        queue.add(10);
        queue.add(1);
        queue.add(5);
        queue.add(7);
        queue.add(8);
        System.out.print(queue.remove()+" ");
        System.out.print(queue.remove()+" ");
        System.out.print(queue.remove()+" ");
        System.out.print(queue.remove()+" ");
        System.out.print(queue.remove()+" ");
        System.out.print(queue.remove()+" ");
    }
}
 
执行返回
1 2 5 7 8 10 
Process finished with exit code 0
不可以加入null,因为无法比较,所有需要去除null

2.对象加入priorityQueue,需要有属性可以比较,并且实现比较接口Comparable,可实现从小到大排序和从大到小排序
```java
package com.example.demo.suanfa.binary.heap;
import org.springframework.cache.annotation.Cacheable;
public class Student implements Comparable {
    private int age;
    private String name;
    public Student(int age, String name) {
        this.age = age;
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public int compareTo(Object o) {
        Student o1 = (Student) o;
        return this.age-o1.age;
    }
}
package com.example.demo.suanfa.binary.heap;
import java.util.PriorityQueue;
import java.util.Queue;
public class HeapTest {
    public static void main(String[] args) {
        Queue<Student> qStudent = new PriorityQueue<>();
        qStudent.offer(new Student(3,"小明"));
        qStudent.offer(new Student(2,"小红"));
        qStudent.offer(new Student(1,"小蓝"));
        System.out.println(qStudent.remove().getAge()+" " );
        System.out.println(qStudent.remove().getAge()+" " );
        System.out.println(qStudent.remove().getAge()+" " );
    }
}
执行返回 1 2 3
如果没有实现compare接口  报错
 




















