Java數(shù)據(jù)結(jié)構(gòu)——優(yōu)先隊列

2.7 優(yōu)先級隊列

無序數(shù)組實現(xiàn)

要點

  1. 入隊保持順序
  2. 出隊前找到優(yōu)先級最高的出隊,相當(dāng)于一次選擇排序
public class PriorityQueue1<E extends Priority> implements Queue<E> {

    Priority[] array;
    int size;

    public PriorityQueue1(int capacity) {
        array = new Priority[capacity];
    }

    @Override // O(1)
    public boolean offer(E e) {
        if (isFull()) {
            return false;
        }
        array[size++] = e;
        return true;
    }

    // 返回優(yōu)先級最高的索引值
    private int selectMax() {
        int max = 0;
        for (int i = 1; i < size; i++) {
            if (array[i].priority() > array[max].priority()) {
                max = i;
            }
        }
        return max;
    }

    @Override // O(n)
    public E poll() {
        if (isEmpty()) {
            return null;
        }
        int max = selectMax();
        E e = (E) array[max];
        remove(max);
        return e;
    }

    private void remove(int index) {
        if (index < size - 1) {
            System.arraycopy(array, index + 1,
                    array, index, size - 1 - index);
        }
        array[--size] = null; // help GC
    }

    @Override
    public E peek() {
        if (isEmpty()) {
            return null;
        }
        int max = selectMax();
        return (E) array[max];
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public boolean isFull() {
        return size == array.length;
    }
}
  • 視頻中忘記了 help GC,注意一下

有序數(shù)組實現(xiàn)

要點

  1. 入隊后排好序,優(yōu)先級最高的排列在尾部
  2. 出隊只需刪除尾部元素即可
public class PriorityQueue2<E extends Priority> implements Queue<E> {

    Priority[] array;
    int size;

    public PriorityQueue2(int capacity) {
        array = new Priority[capacity];
    }

    // O(n)
    @Override
    public boolean offer(E e) {
        if (isFull()) {
            return false;
        }
        insert(e);
        size++;
        return true;
    }

    // 一輪插入排序
    private void insert(E e) {
        int i = size - 1;
        while (i >= 0 && array[i].priority() > e.priority()) {
            array[i + 1] = array[i];
            i--;
        }
        array[i + 1] = e;
    }

    // O(1)
    @Override
    public E poll() {
        if (isEmpty()) {
            return null;
        }
        E e = (E) array[size - 1];
        array[--size] = null; // help GC
        return e;
    }

    @Override
    public E peek() {
        if (isEmpty()) {
            return null;
        }
        return (E) array[size - 1];
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public boolean isFull() {
        return size == array.length;
    }
}

堆實現(xiàn)

計算機(jī)科學(xué)中,堆是一種基于樹的數(shù)據(jù)結(jié)構(gòu),通常用完全二叉樹實現(xiàn)。堆的特性如下

  • 在大頂堆中,任意節(jié)點 C 與它的父節(jié)點 P 符合 P.value \geq C.value
  • 而小頂堆中,任意節(jié)點 C 與它的父節(jié)點 P 符合 P.value \leq C.value
  • 最頂層的節(jié)點(沒有父親)稱之為 root 根節(jié)點

In computer science, a heap is a specialized tree-based data structure which is essentially an almost complete tree that satisfies the heap property: in a max heap, for any given node C, if P is a parent node of C, then the key (the value) of P is greater than or equal to the key of C. In a min heap, the key of P is less than or equal to the key of C. The node at the "top" of the heap (with no parents) is called the root node

例1 - 滿二叉樹(Full Binary Tree)特點:每一層都是填滿的

image.png

例2 - 完全二叉樹(Complete Binary Tree)特點:最后一層可能未填滿,靠左對齊

image.png

例3 - 大頂堆

image.png

例4 - 小頂堆

image.png

完全二叉樹可以使用數(shù)組來表示

image.png

特征

  • 如果從索引 0 開始存儲節(jié)點數(shù)據(jù)
    • 節(jié)點 i 的父節(jié)點為 floor((i-1)/2),當(dāng) i>0
    • 節(jié)點 i 的左子節(jié)點為 2i+1,右子節(jié)點為 2i+2,當(dāng)然它們得 < size
  • 如果從索引 1 開始存儲節(jié)點數(shù)據(jù)
    • 節(jié)點 i 的父節(jié)點為 floor(i/2),當(dāng) i > 1
    • 節(jié)點 i 的左子節(jié)點為 2i,右子節(jié)點為 2i+1,同樣得 < size

代碼

public class PriorityQueue4<E extends Priority> implements Queue<E> {

    Priority[] array;
    int size;

    public PriorityQueue4(int capacity) {
        array = new Priority[capacity];
    }

    @Override
    public boolean offer(E offered) {
        if (isFull()) {
            return false;
        }
        int child = size++;
        int parent = (child - 1) / 2;
        while (child > 0 && offered.priority() > array[parent].priority()) {
            array[child] = array[parent];
            child = parent;
            parent = (child - 1) / 2;
        }
        array[child] = offered;
        return true;
    }


    private void swap(int i, int j) {
        Priority t = array[i];
        array[i] = array[j];
        array[j] = t;
    }

    @Override
    public E poll() {
        if (isEmpty()) {
            return null;
        }
        swap(0, size - 1);
        size--;
        Priority e = array[size];
        array[size] = null;
        
        shiftDown(0);        
        return (E) e;
    }

    void shiftDown(int parent) {
        int left = 2 * parent + 1;
        int right = left + 1;
        int max = parent;
        if (left < size && array[left].priority() > array[max].priority()) {
            max = left;
        }
        if (right < size && array[right].priority() > array[max].priority()) {
            max = right;
        }
        if (max != parent) {
            swap(max, parent);
            shiftDown(max);
        }
    }

    @Override
    public E peek() {
        if (isEmpty()) {
            return null;
        }
        return (E) array[0];
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public boolean isFull() {
        return size == array.length;
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容