数据结构——优先队列PriorityQueue

来源:互联网 发布:双十一网络瘫痪 编辑:程序博客网 时间:2024/06/05 07:24

PriorityQueue

  • 底层原理是二叉堆
  • 继承AbstractQueue抽象类,实现Serializable接口
  • AbstractQueue继承AbstractCollection抽象类,实现Queue接口
  • AbstractCollection实现Collection接口
  • 主要方法为offer(E e)peek()poll()

源码分析

offer(E e)——插入元素

    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;    }

siftUp(int k, E x)——二叉堆的上滤

1. 放在数组末尾2. 与父节点进行比较,找到合适的位置
    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) {            //二叉堆的元素从1开始,优先队列从0开始,所以需要减1寻找父节点            //>>>表示无符号右移,也叫逻辑右移,忽略符号位,空位都以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;    }    @SuppressWarnings("unchecked")    private void siftUpUsingComparator(int k, E x) {        while (k > 0) {            int parent = (k - 1) >>> 1;            Object e = queue[parent];            if (comparator.compare(x, (E) e) >= 0)                break;            queue[k] = e;            k = parent;        }        queue[k] = x;    }

peek()——返回第一个元素,不改变数组内容

    public E peek() {        return (size == 0) ? null : (E) queue[0];    }

poll()——返回第一个元素,且移除该元素,改变队列结构,同二叉堆的deleteMin,使用下滤

    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;    }

siftDown(int k, E x)——二叉堆的下滤操作

1. 将最后一个元素放到位置0处2. 与左右子节点比较,并进行交换,直到将这个元素放到合适的位置
    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;    }    @SuppressWarnings("unchecked")    private void siftDownUsingComparator(int k, E x) {        int half = size >>> 1;        while (k < half) {            int child = (k << 1) + 1;            Object c = queue[child];            int right = child + 1;            if (right < size &&                comparator.compare((E) c, (E) queue[right]) > 0)                c = queue[child = right];            if (comparator.compare(x, (E) c) <= 0)                break;            queue[k] = c;            k = child;        }        queue[k] = x;    }
原创粉丝点击