您的位置:首页 > 产品设计 > UI/UE

PriorityQueue(优先级队列)源码分析及常用方法解析

2019-03-08 13:37 507 查看

一、PriorityQueue详解

特点:

  • 不能为null
  • 元素可以重复
  • 可以又粗打印(每次只打印堆顶)

常用方法:

  • add() 添加元素——不能添加null元素,否则抛空指针异常
  • offer() 添加元素 ——不能添加null元素,否则抛空指针异常
  • peek() 获取队列顶部元素——仅仅获取,没有删除
  • element()获取堆顶元素——队列为空抛异常NoSuchElementException()
  • remove() 删除元素:删除堆顶元素——队列为空的时候抛出异常NoSuchElementException()
  • poll() 删除元素:删除堆顶元素——队列为空的时候返回null

源码分析:

  • 继承关系
    继承了AbstractQueue,AbstractQueue继承了AbstractCollection,实现了Queue接口
public class PriorityQueue<E> extends AbstractQueue<E>
public abstract class AbstractQueue<E>
extends AbstractCollection<E>
implements Queue<E> {
  • 底层数据结构
    用数组存储数据
    用树来组织数据
  • 基本属性
private static final int DEFAULT_INITIAL_CAPACITY = 11;//默认构造容量为11
private transient Object[] queue; //存储对象的数组
private int size = 0;//存储元素的个数
private final Comparator<? super E> comparator; //比较器
private transient int modCount = 0; //版本号
  • 默认值

    默认数组大小为11

  • 构造函数(6个)

//无参构造一个默认容量的数组
public PriorityQueue() {
this(DEFAULT_INITIAL_CAPACITY, null);
}
//构造指定容量的空数组
public PriorityQueue(int initialCapacity) {
this(initialCapacity, null);
}
//构造指定容量的空数组。传入比较器
public PriorityQueue(int initialCapacity,
Comparator<? super E> comparator) {
if (initialCapacity < 1)
throw new IllegalArgumentException();
this.queue = new Object[initialCapacity];
this.comparator = comparator;
}
//传入Collection接口下的集合
public PriorityQueue(Collection<? extends E> c) {
if (c instanceof SortedSet<?>) {
SortedSet<? extends E> ss = (SortedSet<? extends E>) c;
this.comparator = (Comparator<? super E>) ss.comparator();
initElementsFromCollection(ss);
}
else if (c instanceof PriorityQueue<?>) {
PriorityQueue<? extends E> pq = (PriorityQueue<? extends E>) c;
this.comparator = (Comparator<? super E>) pq.comparator();
initFromPriorityQueue(pq);
}
else {
this.comparator = null;
initFromCollection(c);
}
}
//传入一个PriorityQueue接口下的集合
public PriorityQueue(PriorityQueue<? extends E> c) {
this.comparator = (Comparator<? super E>) c.comparator();
initFromPriorityQueue(c);
}
public PriorityQueue(SortedSet<? extends E> c) {
this.comparator = (Comparator<? super E>) c.comparator();
initElementsFromCollection(c);
}
  • 增长方式
    容量<64时,2倍扩容
    容量>64时,1.5倍扩容
private void grow(int minCapacity) {
int oldCapacity = queue.length;
int newCapacity = oldCapacity + ((oldCapacity < 64) ?
(oldCapacity + 2) :
(oldCapacity >> 1));
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
queue = Arrays.copyOf(queue, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
  • CRUD方法研究
    1.添加元素:
    add() / offer()
public boolean add(E e) {
return offer(e);  //调用offer()
}
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; //直接将当前添加的数据放在0号位置
else
siftUp(i, e); //队中有元素,调用siftUp()向上调整
return true;
}
private void siftUp(int k, E x) {
if (comparator != null)
siftUpUsingComparator(k, x);
else
siftUpComparable(k, x);
}

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

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

2.删除元素:
remove()/ poll()

public E remove() {
E x = poll();  //调用poll进行删除
if (x != null) //当前队列不为空,则返回删除的元素
return x;
else   //当前队列为空,返回异常NoSuchElementException()
throw new NoSuchElementException();
}

public E poll() {
if (size == 0)  //队列中无元素,返回null
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);
}
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;
}

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

3.获取堆顶元素:
peek() / element()

public E peek() {
if (size == 0)  //队列中没有元素,返回null
return null;
return (E) queue[0]; //队列不空,返回当前堆顶元素
}
public E element() {
E x = peek(); //调用peek()进行获取
if (x != null)
return x;
else
throw new NoSuchElementException();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐