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

一、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();
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值