PriorityQueue源码分析

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值