成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

優先隊列PriorityQueue,有空了解一下嗎?

開發 前端
怎么找呢?新元素(x)不斷與父節點(e)比較,如果新元素(x)大于等于父節點(e),則已滿足堆的性質,退出循環,k就是新元素最終的位置,否則,將父節點往下移(queue[k]=e),繼續向上尋找。

前言

PriorityQueue這個隊列不知道大家使用過嗎,反正我用的很少,主要對它不是很了解,今天我帶領大家剖析下PriorityQueue這個優先級隊列。

PriorityQueue介紹

顧名思義,PriorityQueue是優先隊列的意思。優先隊列的作用是能保證每次取出的元素都是隊列中權值最小的。這里牽涉到了大小關系,元素大小的評判可以通過元素本身的自然順序(natural ordering),也可以通過構造時傳入的比較器。

  • PriorityQueue實現了Queue接口,最大的特點是存取具有優先級,就是根據元素的順序來決定
  • PriorityQueue是一個無界的容器
  • PriorityQueue底層是基于堆實現的
  • 不允許放入null元素
  • PriorityQueue不是線程安全的

圖片圖片

以上是PriorityQueue的類圖,

  • 繼承了AbstractQueue抽象類,實現了Queue接口,具備隊列的操作方法
  • 實現了Seriablizable接口,支持序列化

構造方法

方法

說明

PriorityQueue()

構造一個初始容量為11的優先隊列

PriorityQueue(Comparator<? super E> comparator)

構造一個自定義排序器的優先隊列

PriorityQueue(SortedSet<? extends E> c)

構造一個基于SortedSet內容的優先隊列

關鍵方法

方法

說明

add(E e)

添加元素,如果超過隊列長度,拋出異常

offer(E e)

添加元素,如果超過隊列長度返回false

remove()

獲取下個元素,如果沒有拋出異常

poll()

獲取下個元素,如果沒有返回null

element()

查看下個元素的內容,如果沒有拋異常

peek()

查看下個元素的內容,如果沒有返回null

使用案例

  1. 優先隊列功能測試
@Test
    public void test1() {
        Queue<Integer> queue = new PriorityQueue<>();
        queue.offer(5);
        queue.offer(4);
        queue.offer(1);
        queue.offer(9);
        queue.offer(3);
        queue.offer(2);

        // 打印,排序
        Integer poll = null;
        while ((poll = queue.poll()) != null) {
            System.out.println(poll);
        }
    }

運行結果:

圖片圖片

  1. 自定義排序器
@Test
    public void test2() {
        // 自定義排序,倒序
        Queue<Integer> queue = new PriorityQueue<>(Collections.reverseOrder());
        queue.offer(5);
        queue.offer(4);
        queue.offer(1);
        queue.offer(9);
        queue.offer(3);
        queue.offer(2);

        // 打印,排序
        Integer poll = null;
        while ((poll = queue.poll()) != null) {
            System.out.println(poll);
        }
    }

運行結果:

圖片圖片

實現機制

PriorityQueue通過堆實現,具體說是通過完全二叉樹(complete binary tree)實現的小頂堆(任意一個非葉子節點的權值,都不大于其左右子節點的權值),也就意味著可以通過數組來作為PriorityQueue的底層實現。

圖片圖片

上圖中我們給每個元素按照層序遍歷的方式進行了編號,如果你足夠細心,會發現父節點和子節點的編號是有聯系的,更確切的說父子節點的編號之間有如下關系:

leftNo = parentNo*2+1

rightNo = parentNo*2+2

parentNo = (nodeNo-1)/2

通過上述三個公式,可以輕易計算出某個節點的父節點以及子節點的下標。這也就是為什么可以直接用數組來存儲堆的原因。

源碼解析

成員變量

transient Object[] queue;
    /**
     * The number of elements in the priority queue.
     */
private int size = 0;

    /**
     * The comparator, or null if priority queue uses elements'
     * natural ordering.
     */
private final Comparator<? super E> comparator;

    /**
     * The number of times this priority queue has been
     * <i>structurally modified</i>.  See AbstractList for gory details.
     */
transient int modCount = 0;
  • queue就是實際存儲元素的數組。
  • size表示當前元素個數。
  • comparator為比較器,可以為null。
  • modCount記錄修改次數。

構造方法

public PriorityQueue(int initialCapacity,
                         Comparator<? super E> comparator) {
        // Note: This restriction of at least one is not actually needed,
        // but continues for 1.5 compatibility
        if (initialCapacity < 1)
            throw new IllegalArgumentException();
        this.queue = new Object[initialCapacity];
        this.comparator = comparator;
    }
  • 初始化了queue和comparator

添加元素offer

public boolean offer(E e) {
        // 如果元素為空,拋出空指針
        if (e == null)
            throw new NullPointerException();
        // 修改次數+1
        modCount++;
        int i = size;
        // 首先確保數組長度是夠的,如果不夠,調用grow方法動態擴展。
        if (i >= queue.length)
            grow(i + 1);
        size = i + 1;
        // 如果是第一次添加,直接添加到第一個位置即可 (queue[0]=e)
        if (i == 0)
            queue[0] = e;
        else
            // 否則將其放入最后一個位置,但同時向上調整,直至滿足堆的性質 (siftUp) 
            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);
    }

如果原長度比較小,大概就是擴展為兩倍,否則就是增加50%,使用Arrays.copyOf方法拷貝數組。

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

參數k表示插入位置,x表示新元素。k初始等于數組大小,即在最后一個位置插入。代碼的主要部分是:往上尋找x真正應該插入的位置,這個位置用k表示。

怎么找呢?新元素(x)不斷與父節點(e)比較,如果新元素(x)大于等于父節點(e),則已滿足堆的性質,退出循環,k就是新元素最終的位置,否則,將父節點往下移(queue[k]=e),繼續向上尋找。

總結

優先級可以有相同的,內部元素不是完全有序的,如果遍歷輸出,除了第一個,其他沒有特定順序。查看頭部元素的效率很高,為O(1),入隊、出隊效率比較高,為O(log2(N)),構建堆的效率為O(N)。根據值查找和刪除元素的效率比較低,為O(N)。

責任編輯:武曉燕 來源: JAVA旭陽
相關推薦

2020-12-10 08:44:35

WebSocket輪詢Comet

2022-03-24 13:36:18

Java悲觀鎖樂觀鎖

2019-12-26 15:33:57

RedisHash架構

2020-02-10 14:26:10

GitHub代碼倉庫

2019-02-20 14:16:43

2018-06-05 17:40:36

人工智能語音識別

2024-04-11 12:19:01

Rust數據類型

2022-09-21 12:01:22

消息隊列任務隊列任務調度

2022-03-07 06:34:22

CQRS數據庫數據模型

2020-03-01 17:53:38

Excel大數據微軟

2018-07-17 14:42:50

2023-11-18 09:09:08

GNUBSD協議

2024-02-28 18:22:13

AI處理器

2021-05-18 08:31:46

緩存HTTP服務器

2018-04-12 17:29:43

眾籌Linux紅旗軟件

2021-01-21 10:23:43

數據庫架構技術

2024-08-22 12:31:05

2018-04-25 06:46:52

2018-08-08 09:30:29

服務器知識Linux系統

2023-03-02 08:00:55

包管理工具pnpm 包
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日本一区视频在线观看 | 欧美高清免费 | www.色午夜.com | 日韩一区精品 | 免费av手机在线观看 | 日韩精品免费在线观看 | 日本精品久久久久久久 | 精品国产欧美一区二区三区成人 | 羞羞视频网页 | 日本中文字幕在线观看 | 一区二区av| 中文字幕a√ | 一级一级毛片免费看 | 日韩精品一区二区三区久久 | 久久99国产精一区二区三区 | 免费簧片视频 | 四虎海外 | 日韩午夜 | 久久99精品久久久久 | 亚洲成人精品一区 | www.4hu影院 | 日韩视频一区二区 | 欧美精品成人 | 91大片| 天堂资源最新在线 | 日韩av成人在线观看 | 成人免费视频网站在线看 | 国产91网址| 一区二区三区四区国产精品 | 欧美久久久久久久久中文字幕 | 日本天天操 | 成人av电影免费在线观看 | 亚洲免费精品 | av香蕉| 欧美中文一区 | 日本特黄a级高清免费大片 成年人黄色小视频 | 国产中文视频 | 国产女人与拘做受免费视频 | 一区二区视频 | 天天操夜夜操 | 卡通动漫第一页 |