PriorityQueue源码分析

来源:互联网 发布:手机手写输入软件 编辑:程序博客网 时间:2024/06/08 06:29

1, 概念PriorityQueue是优先队列,作用是保证每次取出的元素都是队列中权值最小的,具体是通过完全二叉树实现的最小堆(任一位置的值都不大于其左右孩子的值)完成的。重要变量如下,

private static final long serialVersionUID = -7720805057305804111L; // 版本系列号private static final int DEFAULT_CAPACITY = 11;private static final double DEFAULT_INIT_CAPACITY_RATIO = 1.1;private static final int DEFAULT_CAPACITY_RATIO = 2;private int size; // 添加的元素private Comparator<? super E> comparator;private transient E[] elements;

2, 构造方法

有6个构造方法,

public PriorityQueue(int initialCapacity, Comparator<? super E> comparator) {        if (initialCapacity < 1) {            throw new IllegalArgumentException("initialCapacity < 1: " + initialCapacity);        }        elements = newElementArray(initialCapacity);        this.comparator = comparator;}private E[] newElementArray(int capacity) {        return (E[]) new Object[capacity];    }

数组的大小,以及比较方式。

3 add方法

PriorityQueue不允许添加null元素, 利用二叉树来实现最小堆。

public boolean add(E o) {        return offer(o);    }public boolean offer(E o) {        if (o == null) {            throw new NullPointerException("o == null");        }        growToSize(size + 1); // 是否需要扩容        elements[size] = o;        siftUp(size++); // 利用二叉树调整最小堆        return true;    }private void growToSize(int size) { // 扩容为原来的2倍        if (size > elements.length) {            E[] newElements = newElementArray(size * DEFAULT_CAPACITY_RATIO);            System.arraycopy(elements, 0, newElements, 0, elements.length);            elements = newElements;        }    }private void siftUp(int childIndex) {        E target = elements[childIndex];        int parentIndex;        while (childIndex > 0) {            parentIndex = (childIndex - 1) / 2;            E parent = elements[parentIndex];            if (compare(parent, target) <= 0) {                break;            }            elements[childIndex] = parent;            childIndex = parentIndex;        }        elements[childIndex] = target;    }

4 获取方法

poll

获取并且删除第一个(最小)元素

peek

获取第一个(最小)元素

poll方法如下,

public E poll() {        if (isEmpty()) {            return null;        }        E result = elements[0];        removeAt(0);        return result;    }

5 删除方法

从头查找并删除第一个为o的元素

public boolean remove(Object o) {        if (o == null) {            return false;        }        for (int targetIndex = 0; targetIndex < size; targetIndex++) {            if (o.equals(elements[targetIndex])) {                removeAt(targetIndex);                return true;            }        }        return false;    }private void removeAt(int index) {        size--;        E moved = elements[size];        elements[index] = moved;        siftDown(index);        elements[size] = null;        if (moved == elements[index]) {            siftUp(index);        }    }

0 0
原创粉丝点击