什么是优先队列

普通队列:先进先出,后进后出

优先队列:出队顺序和入队顺序无关,和优先级相关

实现优先队列的数据结构 入队 出队(拿出最大元素)
普通线性结构 O(1) O(n)
顺序线性结构 O(n) O(1)
O(logn) O(logn)
interface Queue<E> {

    int getSize();
    boolean isEmpty();
    void enqueue(E element);
    E dequeue();
    E getFront();
}

class PriorityQueue<E extends Comparable<E>> implements Queue<E>{

    private MaxHeap<E> maxHeap;

    public PriorityQueue(){

        maxHeap = new MaxHeap();
    }

    @Override
    public int getSize(){

        return maxHeap.size();
    }

    @Override
    public boolean isEmpty(){

        return maxHeap.isEmpty();
    }

    @Override
    public E getFront(){

        return maxHeap.findMax();
    }

    @Override
    public void enqueue(E element){

        maxHeap.add(element);
    }

    @Override
    public E dequeue(){

        return maxHeap.extractMax();
    }
}

class MaxHeap<E extends Comparable<E>>{

    private Array<E> heap;

    public MaxHeap(int capacity){

        heap = new Array<>(capacity);
    }

    public MaxHeap(){

        heap = new Array<>(10);
    }

    public MaxHeap(E[] arr){

        heap = new Array<>(arr);
        heapify(arr);
    }

    public int size(){

        return heap.getSize();
    }

    public boolean isEmpty(){

        return heap.getSize() == 0;
    }

    public int parent(int index){

        if (index == 0) {
            throw new IllegalArgumentException("根节点没有父节点");
        }
        return (index - 1) / 2;
    }

    private int leftChild(int index){

        return 2 * index + 1;
    }

    private int rightChild(int index){

        return 2 * index + 2;
    }

    public void add(E e){

        heap.addLast(e);
        siftUp(size() - 1);
    }

    private void siftUp(int index){

        while (index > 0 && heap.get(index).compareTo(heap.get(parent(index))) > 0){

            heap.swap(index, parent(index));
            index = parent(index);
        }
    }

    public E findMax(){

        if (size() == 0){
            throw new IllegalArgumentException("堆为空");
        }

        return heap.get(0);
    }

    public E extractMax(){

        E max = findMax();

        heap.swap(0, size() - 1);
        heap.remove(size() - 1);
        siftDown(0);

        return max;
    }

    public void siftDown(int index){

        while (leftChild(index) < size()){

            int max = leftChild(index);

            if (rightChild(index) < size() && heap.get(leftChild(index)).compareTo(heap.get(rightChild(index))) < 0){
                max = rightChild(index);
            }

            if (heap.get(index).compareTo(heap.get(max)) >= 0){
                break;
            }

            heap.swap(index, max);
            index = max;
        }
    }

    public void heapify(E[] arr){

        if (arr.length > 1){
            for (int i = parent(arr.length - 1); i >= 0; i--) {
                siftDown(i);
            }
        }
    }

    public E replace(E e){

        E max = findMax();
        heap.set(e, 0);
        siftDown(0);

        return max;
    }
}

class Array<E>{

    private E[] data;
    private int size;

    public Array(int capacity){

        data = (E[]) new Object[capacity];
        size = 0;
    }

    public Array(E[] arr){

        data = (E[]) new Object[arr.length];

        for (int i = 0; i < arr.length; i++) {
            data[i] = arr[i];
        }

        size = arr.length;
    }

    public Array(){

        data = (E[]) new Object[10];
        size = 0;
    }

    public int getSize(){

        return size;
    }

    public void swap(int index1, int index2){

        E temp;
        temp = data[index1];
        data[index1] = data[index2];
        data[index2] = temp;
    }

    public E get(int index){

        if (index < 0 || index >= size){
            throw new IllegalArgumentException("索引值非法");
        }

        return data[index];
    }

    public void set(E e, int index){

        if (index < 0 || index >= size){
            throw new IllegalArgumentException("索引值非法");
        }

        data[index] = e;
    }

    public void add(E e, int index){

        if (index < 0 || index > size){
            throw new IllegalArgumentException("索引值非法");
        }

        if (size == data.length){
            resize(2 * data.length);
        }

        for (int i = index - 1; i >= index; i++) {
            data[i + 1] = data[i];
        }

        data[index] = e;
        size++;
    }

    public void addLast(E e){
        add(e, size);
    }

    public void remove(int index){

        if (index < 0 || index >= size){
            throw new IllegalArgumentException("索引值非法");
        }

        for (int i = index + 1; i < size; i++) {
            data[i - 1] = data[i];
        }

        size--;
        data[size] = null;

        if (size == data.length / 2 && data.length / 2 != 0){
            resize(data.length / 2);
        }
    }

    public void resize(int newCapacity){

        E[] temp = (E[])new Object[newCapacity];

        for (int i = 0; i < size; i++) {
            temp[i] = data[i];
        }

        data = temp;
    }

    @Override
    public String toString(){

        StringBuilder str = new StringBuilder();
        str.append("[");

        for (int i = 0; i < size; i++) {

            str.append(data[i]);

            if (i != size - 1){
                str.append(", ");
            }
        }

        str.append("]");

        return str.toString();
    }
}

优先队列的优势:不需要一次性知道所有的数据,也不用把所有的数据进行存储,而是采用数据流的方式获取数据,每当获取到一个数据,就进行排序比较,实时更新,在数据规模很大的时候,可以快速的知道最大的元素是多少