最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java優(yōu)先隊(duì)列PriorityQueue超全解析

 更新時間:2026年03月16日 11:02:52   作者:Porunarufu  
在Java集合框架中,PriorityQueue是一個非常特殊的隊(duì)列實(shí)現(xiàn),它不遵循典型的先進(jìn)先出規(guī)則,而是按照元素的自然排序順序或提供的比較器來對元素進(jìn)行排序,這篇文章主要介紹了Java優(yōu)先隊(duì)列PriorityQueue的相關(guān)資料,需要的朋友可以參考下

一、基本定義與特性

  1. 本質(zhì)PriorityQueue 是 Java 集合框架中 Queue 接口的實(shí)現(xiàn)類,基于堆(Heap) 數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)(默認(rèn)是最小堆),底層通過數(shù)組存儲元素。
  2. 核心特性
    • 隊(duì)列中的元素會按照優(yōu)先級順序出隊(duì),而非先進(jìn)先出(FIFO);
    • 不允許存儲 null 元素;
    • 非線程安全,多線程場景需使用 PriorityBlockingQueue;
    • 容量可自動擴(kuò)容(默認(rèn)初始容量為 11,擴(kuò)容規(guī)則:容量 < 64 時翻倍,≥64 時擴(kuò)容 50%);
    • 迭代器遍歷的結(jié)果不保證有序,僅出隊(duì)(poll()/remove())時保證優(yōu)先級順序。

二、關(guān)于堆

堆的核心維度具體內(nèi)容
定義完全二叉樹結(jié)構(gòu),滿足 “堆序性”:- 最小堆:任意節(jié)點(diǎn)值 ≤ 其子節(jié)點(diǎn)值(根節(jié)點(diǎn)為全局最小值);- 最大堆:任意節(jié)點(diǎn)值 ≥ 其子節(jié)點(diǎn)值(根節(jié)點(diǎn)為全局最大值)。
存儲結(jié)構(gòu)基于數(shù)組實(shí)現(xiàn)(利用完全二叉樹的特性):- 根節(jié)點(diǎn):數(shù)組索引 0;- 索引 i 的節(jié)點(diǎn) → 左子節(jié)點(diǎn) 2i+1、右子節(jié)點(diǎn) 2i+2、父節(jié)點(diǎn) (i-1)/2(整數(shù)除法);- 無需連續(xù)存儲空節(jié)點(diǎn),空間利用率高。
核心操作1. 插入(siftUp / 向上調(diào)整):新元素插入數(shù)組尾部,從下往上對比父節(jié)點(diǎn),不滿足堆序性則交換,直到堆序性恢復(fù)(時間復(fù)雜度 O (log n));2. 刪除堆頂(siftDown / 向下調(diào)整):移除根節(jié)點(diǎn),將數(shù)組最后一個元素移到根節(jié)點(diǎn),從上往下對比子節(jié)點(diǎn),不滿足堆序性則交換(選更小 / 更大的子節(jié)點(diǎn)),直到堆序性恢復(fù)(時間復(fù)雜度 O (log n));3. 堆化(heapify):將無序數(shù)組轉(zhuǎn)換為堆結(jié)構(gòu),從最后一個非葉子節(jié)點(diǎn)(索引 size/2 - 1)開始,逐個執(zhí)行 siftDown(時間復(fù)雜度 O (n))。
特性- 僅能高效獲取 / 刪除堆頂元素(優(yōu)先級最高);- 遍歷無序(完全二叉樹的特性決定,僅堆頂有序);- 支持動態(tài)擴(kuò)容(數(shù)組滿時擴(kuò)容,規(guī)則由實(shí)現(xiàn)決定)。

1.優(yōu)先級規(guī)則 ↔ 堆的類型

  • PriorityQueue默認(rèn)實(shí)現(xiàn)最小堆:依賴元素的 Comparable 接口(compareTo() 定義自然順序),本質(zhì)是維護(hù)最小堆的堆序性;
  • 自定義優(yōu)先級(如最大堆):傳入 Comparator 比較器,本質(zhì)是修改堆的 “堆序性判斷邏輯”,例如:
// 最大堆:Comparator修改siftUp/siftDown的比較規(guī)則,讓父節(jié)點(diǎn)≥子節(jié)點(diǎn)
PriorityQueue<Integer> maxHeap = new PriorityQueue<>((a, b) -> b - a);
  • 異常根源:若元素未實(shí)現(xiàn) Comparable 且無 Comparator,堆序性無法判斷,運(yùn)行時拋 ClassCastException。

2. 存儲結(jié)構(gòu) ↔ 堆的數(shù)組存儲

  • PriorityQueue 底層直接復(fù)用堆的數(shù)組存儲邏輯
    • 初始容量 11(數(shù)組初始長度),擴(kuò)容規(guī)則:容量 < 64 時翻倍,≥64 時擴(kuò)容 50%(堆的數(shù)組存儲需要連續(xù)空間,擴(kuò)容是為了滿足堆的動態(tài)插入);
    • 空隊(duì)列時數(shù)組為默認(rèn)空數(shù)組,添加第一個元素時初始化長度為 11。

3. 核心方法 ↔ 堆的核心操作

PriorityQueue 的所有核心方法,本質(zhì)都是調(diào)用堆的插入 / 刪除 / 堆化操作:

        堆的存儲是基于數(shù)組的完全二叉樹映射—— 利用完全二叉樹 “層序排列無空洞” 的特性,將樹節(jié)點(diǎn)按層序順序存入數(shù)組,無需額外存儲指針(如鏈?zhǔn)酱鎯Γ?,空間效率和索引計(jì)算效率極高,這也是 Java PriorityQueue 底層選擇數(shù)組存儲堆的核心原因。

4.存儲核心原理

  1. 為什么選數(shù)組?堆的本質(zhì)是完全二叉樹(除最后一層外,每一層節(jié)點(diǎn)數(shù)都滿;最后一層節(jié)點(diǎn)靠左排列),這種結(jié)構(gòu)的節(jié)點(diǎn)可以通過 “層序遍歷” 的順序無間隙地填入數(shù)組,且父 / 子節(jié)點(diǎn)的索引可通過簡單數(shù)學(xué)公式計(jì)算無需像普通二叉樹那樣存儲左 / 右子節(jié)點(diǎn)指針,空間利用率接近 100%。
  2. 核心映射規(guī)則(必記)假設(shè)堆的底層數(shù)組為 queue,節(jié)點(diǎn)的數(shù)組索引為 i(從 0 開始),則:

5.可視化示例(最小堆)

以最小堆 [1, 3, 8, 5, 4] 為例,完全二叉樹結(jié)構(gòu)與數(shù)組存儲的對應(yīng)關(guān)系:

        1 (索引0)  ← 堆頂
       /  \
      3(1) 8(2)
     /  \
    5(3) 4(4)

對應(yīng)的底層數(shù)組 queue = [1, 3, 8, 5, 4],驗(yàn)證映射規(guī)則:

  • 索引 1(節(jié)點(diǎn) 3)的父節(jié)點(diǎn):(1-1)/2 = 0(節(jié)點(diǎn) 1);
  • 索引 0(節(jié)點(diǎn) 1)的左子節(jié)點(diǎn):2*0+1=1(節(jié)點(diǎn) 3),右子節(jié)點(diǎn):2*0+2=2(節(jié)點(diǎn) 8);
  • 索引 3(節(jié)點(diǎn) 5)的父節(jié)點(diǎn):(3-1)/2=1(節(jié)點(diǎn) 3),無左右子節(jié)點(diǎn)(2*3+1=7 ≥ 5)。

6.關(guān)鍵節(jié)點(diǎn)類型的索引判斷(堆操作的基礎(chǔ))

基于數(shù)組存儲的特性,可快速判斷節(jié)點(diǎn)類型,這是堆化、siftUp/siftDown 的核心依據(jù):

  1. 葉子節(jié)點(diǎn):索引范圍 [size/2, size-1]size 為堆的元素個數(shù));示例:上述堆 size=5,葉子節(jié)點(diǎn)索引為 [2,4](節(jié)點(diǎn) 8、5、4),葉子節(jié)點(diǎn)無需執(zhí)行 siftDown(無后代可比較)。
  2. 非葉子節(jié)點(diǎn):索引范圍 [0, size/2 - 1];示例:size=5,非葉子節(jié)點(diǎn)索引為 [0,1](節(jié)點(diǎn) 1、3),堆化時僅需遍歷這些節(jié)點(diǎn)執(zhí)行 siftDown。

7.關(guān)于siftUp/siftDown

        siftUp(向上調(diào)整) 和 siftDown(向下調(diào)整),二者是堆(優(yōu)先隊(duì)列底層)維護(hù)「堆序性」的核心操作

操作觸發(fā)場景核心目的核心邏輯(以最小堆為例)
siftUp往堆中插入新元素(如 offer)讓新元素找到正確位置,保證堆序性1. 新元素先放到數(shù)組尾部(堆的最后一個節(jié)點(diǎn));2. 不斷和父節(jié)點(diǎn)比較,若更小則交換;3. 直到滿足「父≤子」或到根節(jié)點(diǎn)。
siftDown1. 刪除堆頂元素(如 poll);2. 堆化(heapify)讓替換到堆頂 / 非葉子節(jié)點(diǎn)的元素歸位,保證堆序性1. 從當(dāng)前節(jié)點(diǎn)(堆頂 / 非葉子節(jié)點(diǎn))開始;2. 不斷和左右子節(jié)點(diǎn)比較,選更小的子節(jié)點(diǎn)交換;3. 直到滿足「父≤子」或到葉子節(jié)點(diǎn)。

        總結(jié)siftUp 是「自下而上」找位置(插入用),siftDown 是「自上而下」找位置(刪堆頂 / 堆化用),最終都是為了讓堆滿足「最小 / 最大堆」的核心規(guī)則。

8.建堆的時間復(fù)雜度

建堆(heapify)的時間復(fù)雜度是 O(n)(而非直覺上的 O (n log n)),這是堆操作中極易混淆的關(guān)鍵點(diǎn),以下用「結(jié)論 + 原理 + 對比」講清楚:

8.1核心結(jié)論

8.2為什么堆化是 O (n)?(通俗推導(dǎo))

堆化的核心是「從最后一個非葉子節(jié)點(diǎn)反向遍歷,執(zhí)行 siftDown」,不同層級的節(jié)點(diǎn)執(zhí)行 siftDown 的次數(shù)不同,葉子節(jié)點(diǎn)甚至無需調(diào)整,整體操作次數(shù)遠(yuǎn)低于 O (n log n):

  1. 堆的結(jié)構(gòu)基礎(chǔ):堆是完全二叉樹,假設(shè)堆的高度為h(根節(jié)點(diǎn)層級為 0,葉子節(jié)點(diǎn)層級為h),節(jié)點(diǎn)總數(shù)n ≈ 2^(h+1) - 1;
  2. 分層計(jì)算操作次數(shù)
    • 層級k的節(jié)點(diǎn)數(shù):2^k 個;
    • 該層級節(jié)點(diǎn)執(zhí)行 siftDown 的最大次數(shù):h - k(越靠近根節(jié)點(diǎn),需要向下調(diào)整的次數(shù)越多;葉子節(jié)點(diǎn)層級h,調(diào)整次數(shù)為 0);
  3. 總操作次數(shù)求和:總次數(shù) = 2^0*(h) + 2^1*(h-1) + 2^2*(h-2) + ... + 2^(h-1)*1;數(shù)學(xué)求和后可推導(dǎo):總次數(shù) ≈ 2n(收斂到 O (n))。

8.3對比理解(為什么不是 O (n log n)?)

如果用「逐個 offer 元素(每次 siftUp)」的方式建堆,時間復(fù)雜度是 O (n log n):

  • 每個元素插入時,最多需要從葉子節(jié)點(diǎn)調(diào)整到根節(jié)點(diǎn)(最多h=log n次操作);
  • n個元素總操作次數(shù) = n * log n,即 O (n log n)。

而堆化用 siftDown,僅非葉子節(jié)點(diǎn)需要調(diào)整,且越靠近葉子的節(jié)點(diǎn)調(diào)整次數(shù)越少,整體效率遠(yuǎn)高于逐個插入 —— 這也是 PriorityQueue 初始化集合時選擇 heapify(而非循環(huán) offer)的核心原因。

總結(jié):堆化(O (n))是「批量優(yōu)化版」建堆,利用完全二叉樹的層級特性減少無效調(diào)整;逐個插入(O (n log n))是「動態(tài)零散版」,無批量優(yōu)化,效率更低。

三、堆(PriorityQueue)常用接口 / API 全解析

Java 中堆的操作完全通過 PriorityQueue 類暴露(實(shí)現(xiàn) Queue 接口),以下是開發(fā)中最常用的接口,按「核心操作、查詢操作、輔助操作」分類,結(jié)合堆的底層邏輯講解(默認(rèn)最小堆,最大堆僅比較器不同):

1.接口體系背景

   PriorityQueue 實(shí)現(xiàn)了 java.util.Queue 接口,間接繼承 Collection/Iterable,所有接口均圍繞「堆的核心特性(堆頂為極值、O (log n) 插入 / 刪除)」設(shè)計(jì),底層關(guān)聯(lián) siftUp/siftDown 等堆操作。

2.核心操作(堆的插入 / 刪除)

方法簽名功能說明關(guān)鍵細(xì)節(jié)(參數(shù) / 返回 / 異常 / 底層堆操作)
boolean offer(E e)向堆中插入元素(推薦使用,非阻塞)

- 參數(shù):e 為待插入元素(不能為 null,否則拋 NullPointerException);

- 返回:插入成功返回 true(堆自動擴(kuò)容,幾乎不會返回 false);

- 底層:元素插入數(shù)組尾部 → 執(zhí)行 siftUp(向上調(diào)整),時間復(fù)雜度 O (log n)。

boolean add(E e)向堆中插入元素(推薦使用,非阻塞)

- 異常:元素為 null 拋 NullPointerException;容量不足時(理論上)拋 IllegalStateException(但 PriorityQueue 自動擴(kuò)容,極少觸發(fā));

- 底層:同 offer,依賴 siftUp。

E poll()刪除并返回堆頂元素(優(yōu)先級最高,最小堆為最小值)

- 返回:堆為空時返回 null;非空時返回堆頂元素;

- 底層:尾元素替換堆頂 → 執(zhí)行 siftDown(向下調(diào)整),時間復(fù)雜度 O (log n)。

boolean remove(Object o)刪除堆中指定元素(若存在)

- 參數(shù):o 為待刪除元素;

- 返回:刪除成功返回 true,失敗返回 false;

- 底層:遍歷數(shù)組找元素索引(O (n))→ 尾元素替換目標(biāo)位置 → 執(zhí)行 siftUp/siftDown 調(diào)整,時間復(fù)雜度 O (n)(遍歷占主導(dǎo))。

3.輔助操作(堆的清空 / 遍歷)

方法簽名功能說明關(guān)鍵細(xì)節(jié)
void clear()清空堆中所有元素- 底層:將數(shù)組元素置為 null,size 置 0,無堆調(diào)整,O (n)(需遍歷置空)。
Iterator<E> iterator()獲取堆的迭代器

- 返回:Iterator 實(shí)例;

- 關(guān)鍵:迭代器遍歷的是堆的底層數(shù)組,結(jié)果無序(僅堆頂有序);

- 注意:遍歷過程中修改堆(如 offer/poll)會觸發(fā)快速失?。?code>ConcurrentModificationException)。

總結(jié) 

到此這篇關(guān)于Java優(yōu)先隊(duì)列PriorityQueue的文章就介紹到這了,更多相關(guān)Java優(yōu)先隊(duì)列PriorityQueue內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 分析Java非阻塞算法Lock-Free的實(shí)現(xiàn)

    分析Java非阻塞算法Lock-Free的實(shí)現(xiàn)

    非阻塞算法一般會使用CAS來協(xié)調(diào)線程的操作。雖然非阻塞算法有諸多優(yōu)點(diǎn),但是在實(shí)現(xiàn)上要比基于鎖的算法更加繁瑣和負(fù)責(zé)。本文將會介紹兩個是用非阻塞算法實(shí)現(xiàn)的數(shù)據(jù)結(jié)構(gòu)。
    2021-06-06
  • 基于SpringBoot制作一個PDF切圖小工具

    基于SpringBoot制作一個PDF切圖小工具

    這篇文章主要為大家詳細(xì)介紹了如何基于SpringBoot制作一個PDF切圖小工具,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-01-01
  • SpringBoot小程序推送信息的項(xiàng)目實(shí)踐

    SpringBoot小程序推送信息的項(xiàng)目實(shí)踐

    本文主要介紹了SpringBoot小程序推送信息的項(xiàng)目實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • Java詳細(xì)分析String類與StringBuffer和StringBuilder的使用方法

    Java詳細(xì)分析String類與StringBuffer和StringBuilder的使用方法

    當(dāng)對字符串進(jìn)行修改的時候,需要使用 StringBuffer 和 StringBuilder類,和String類不同的是,StringBuffer和 StringBuilder類的對象能夠被多次的修改,并且不產(chǎn)生新的未使用對象
    2022-04-04
  • Java String方法獲取字符出現(xiàn)次數(shù)及字符最大相同部分示例

    Java String方法獲取字符出現(xiàn)次數(shù)及字符最大相同部分示例

    這篇文章主要介紹了Java String方法獲取字符出現(xiàn)次數(shù)及字符最大相同部分,涉及java字符串的遍歷、比較、計(jì)算等相關(guān)操作技巧,需要的朋友可以參考下
    2017-09-09
  • java隨機(jī)生成10位數(shù)的字符串ID

    java隨機(jī)生成10位數(shù)的字符串ID

    這篇文章主要為大家詳細(xì)介紹了java隨機(jī)生成10位數(shù)字符串ID的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • Java中URL的處理方法詳解

    Java中URL的處理方法詳解

    URL(Uniform?Resource?Locator)中文名為統(tǒng)一資源定位符,有時也被俗稱為網(wǎng)頁地址,表示為互聯(lián)網(wǎng)上的資源,本文主要為大家介紹了Java是如何處理URL的,感興趣的可以了解一下
    2023-05-05
  • Java?獲取Zookeeper節(jié)點(diǎn)下所有數(shù)據(jù)詳細(xì)步驟

    Java?獲取Zookeeper節(jié)點(diǎn)下所有數(shù)據(jù)詳細(xì)步驟

    本文介紹了如何使用Java獲取ZooKeeper節(jié)點(diǎn)下所有數(shù)據(jù),實(shí)際應(yīng)用示例中,我們演示了如何從ZooKeeper節(jié)點(diǎn)下獲取配置信息并輸出到控制臺,ZooKeeper是一個開源的分布式協(xié)調(diào)服務(wù),適用于分布式系統(tǒng)中的數(shù)據(jù)同步、配置管理、命名服務(wù)等功能,感興趣的朋友一起看看吧
    2024-11-11
  • 一文帶你掌握J(rèn)ava?SPI的原理和實(shí)踐

    一文帶你掌握J(rèn)ava?SPI的原理和實(shí)踐

    在Java中,我們經(jīng)常會提到面向接口編程,這樣減少了模塊之間的耦合,更加靈活,Java?SPI?(Service?Provider?Interface)就提供了這樣的機(jī)制,本文就來講講它的原理與具體使用吧
    2023-05-05
  • IntelliJ?idea報(bào)junit?no?tasks?available問題的解決辦法

    IntelliJ?idea報(bào)junit?no?tasks?available問題的解決辦法

    這篇文章主要給大家介紹了關(guān)于IntelliJ?idea報(bào)junit?no?tasks?available問題的解決辦法,文中通過圖文介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-11-11

最新評論

图木舒克市| 乌海市| 汽车| 宾阳县| 聊城市| 临夏市| 吉木萨尔县| 井研县| 潮安县| 自治县| 贵德县| 临泽县| 诸城市| 昆明市| 仙居县| 年辖:市辖区| 威远县| 太白县| 福海县| 元谋县| 宁晋县| 孙吴县| 长乐市| 禹州市| 北票市| 论坛| 旬邑县| 六盘水市| 左云县| 武宁县| 阿荣旗| 芒康县| 溧水县| 会东县| 沁水县| 师宗县| 淮南市| 且末县| 衡南县| 宜良县| 扎鲁特旗|