Java筆記(十)堆與優先級隊列


優先級隊列

 

一、PriorityQueue

PriorityQueue是優先級隊列,它實現了Queue接口,它的隊列長度

沒有限制,與一般隊列的區別是,它有優先級概念,每個元素都有優先

級,隊頭的元素永遠都是優先級最高的。PriorityQueue內部是用堆實現的。

一、基本用法

主要構造方法:

public PriorityQueue()
public PriorityQueue(int initialCapacity, Comparator<? super E> comparator)
public PriorityQueue(Collection<? extends E> c) //動態數組大小等於容器中元素的個數

PriorityQueue使用動態數組initialCapacity表示初始數組的大小。舉例:

PriorityQueue<Integer> ints = new PriorityQueue<>();
ints.offer(10);
ints.add(28);
ints.addAll(Arrays.asList(22, 33, 55, 66));
while (ints.peek() != null) {
    System.out.println(ints.poll() + "  ");
}

二、實現原理

內部成員:

private transient Object[] queue;
private int size = 0;
private final Comparator<? super E> comparator;
private transient int modCount = 0;

構造方法:

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

添加元素的代碼

public boolean offer(E e) {
    if(e == null)
        throw new NullPointerException();
    modCount++;
    int i = size;
    if(i >= queue.length) //先確保數組長度是否足夠,如果不夠,用grow方法擴展઀
        grow(i + 1);
    size = i + 1;
    if(i == 0) //如果是第一次添加
        queue[0] = e;
    else //否則將其放入最后一個位置,並向上調整
        siftUp(i, e);return true;
}
private void grow(int minCapacity) {
    int oldCapacity = queue.length;
   // Double size if small; else grow by 50%
    int newCapacity = oldCapacity + ((oldCapacity < 64)
    (oldCapacity + 2) :
    (oldCapacity >> 1));
    // overflow-conscious code
    if(newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    queue = Arrays.copyOf(queue, newCapacity);
}
private void siftUp(int k, E x) {
    if(comparator != null)
        siftUpUsingComparator(k, x);
    else
        siftUpComparable(k, x);
}
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;
}

查看元素頭部元素:

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

刪除頭部元素:略

三、總結

1)實現了優先級隊列,最先出隊的總是優先級最高的,即排序中的第一個。

2)優先級可以有相同的,內部元素不是完全有序的,如果遍歷輸出,除了第一個其他沒有特定順序。、

3)查看頭部元素,入隊出隊的效率都很高

4)根據值查找和刪除元素的效率很低。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM