初識數據結構——優先級隊列(堆!堆!堆!)

在這里插入圖片描述
在這里插入圖片描述
?(click)


今天就讓我們來聊聊這個讓無數程序員又愛又恨的數據結構——堆(Heap)。

一、優先級隊列 vs 普通隊列

特性普通隊列優先級隊列
出隊順序FIFO(先進先出)按優先級高低(默認小的先出)
底層實現數組/鏈表通常用堆實現
時間復雜度O(1)插入O(logN),刪除O(logN)
Java實現Queue接口PriorityQueue類
典型應用場景消息隊列、BFS算法任務調度、TopK問題
隊列
普通隊列
優先級隊列
FIFO
基于優先級
實現方式
有序數組
無序數組

二、堆:一棵"偏心的"完全二叉樹

堆的類型對比

類型特點應用場景
大根堆父節點 ≥ 子節點堆排序(升序)、TopK最小
小根堆父節點 ≤ 子節點堆排序(降序)、TopK最大
二叉堆完全二叉樹實現,常用數組存儲最常用實現
斐波那契堆更優的理論時間復雜度,但實現復雜圖算法優化
// 堆的數組表示
parent(i) = (i-1)/2  // 找父節點
left(i) = 2*i + 1    // 左孩子
right(i) = 2*i + 2    // 右孩子
完全二叉樹
數組存儲
大根堆
小根堆
空間利用率高
索引計算快

三、堆的核心操作:上下調整

操作復雜度對比

操作時間復雜度空間復雜度說明
插入(offer)O(logN)O(1)需要向上調整(shiftUp)
刪除(poll)O(logN)O(1)需要向下調整(shiftDown)
查看(peek)O(1)O(1)直接返回堆頂元素
建堆O(N)O(1)自底向上調整比逐個插入更高效
// 向下調整示例(小根堆)
void shiftDown(int[] arr, int parent, int len) {int child = 2*parent + 1;while (child < len) {// 找出較小的孩子if (child+1 < len && arr[child+1] < arr[child]) child++;// 如果父節點已經比孩子小,調整結束if (arr[parent] <= arr[child]) break;swap(arr, parent, child);  // 交換父子parent = child;            // 繼續向下調整child = 2*parent + 1;}
}

四、堆排序 vs 快速排序

特性堆排序快速排序
時間復雜度O(NlogN)O(NlogN)平均
空間復雜度O(1)O(logN)遞歸棧
穩定性不穩定不穩定
最壞情況O(NlogN)O(N2)
數據訪問模式跳躍訪問(緩存不友好)順序訪問(緩存友好)
適用場景大數據量中小數據量
排序算法
比較排序
堆排序
快速排序
原地排序
不穩定
分治思想
平均更快

五、PriorityQueue使用指南

構造方法對比

構造方法說明
new PriorityQueue<>()默認容量11,自然排序
new PriorityQueue<>(int capacity)指定初始容量
new PriorityQueue<>(Comparator)自定義比較器(可實現大根堆)
new PriorityQueue<>(Collection)用已有集合初始化(自動建堆)
// 大根堆實現
PriorityQueue<Integer> maxHeap = new PriorityQueue<>((a,b) -> b-a);// 自定義對象排序
PriorityQueue<Student> pq = new PriorityQueue<>((s1, s2) -> s1.score != s2.score ? s2.score - s1.score :  // 分數高的在前s1.name.compareTo(s2.name)  // 分數相同按名字
);

六、TopK問題的三種解法對比

方法時間復雜度空間復雜度適用場景
快速排序+取前KO(NlogN)O(logN)數據可全部裝入內存
堆排序O(NlogK)O(K)海量數據,K較小
冒泡K次O(N*K)O(1)K非常小(如K=1,2)
TopK問題
排序法
堆方法
分治法
全排序后取前K
維護大小為K的堆
類似快速選擇
小根堆求最大K
大根堆求最小K

七、堆的常見面試題

1. 堆的建立過程(以小根堆為例)

//向下調整方法(復雜度logN)public static void shiftDown(int[] array, int index){//要調整的父節點int parent = index;//要調整的孩子節點int child = 2*parent + 1;while (child < array.length){//child+1其實代表的是右子樹//判斷左右子樹大小if(child+1<array.length && array[child+1] < array[child]){//左右子樹對調child = child+1;}//判斷左子樹和父節點的大小if (array[child] >= array[parent]){break;}else{int temp = array[parent];array[parent] = array[child];array[child] = temp;//更新父節點和子節點的指向parent = child;child = 2*parent +1;}}}/***建堆操作復雜度O(n)* @param array*/public static void createHeap(int[] array){//要先找到最后一個非葉子節點int lastLeaf  = array.length-1;int lastParent = (lastLeaf-1)/2;for (int i = lastParent; i >= 0; i--){shiftDown(array, i);}}

2. 堆的應用場景總結

應用場景使用的堆類型原因說明
堆排序大根堆/小根堆升序用大根堆,降序用小根堆
TopK最大元素小根堆維護K個元素的小根堆,淘汰小的
TopK最小元素大根堆維護K個元素的大根堆,淘汰大的
任務調度(優先級高的先執行)大根堆優先級高的在堆頂
合并K個有序鏈表小根堆每次取最小節點,效率O(logK)
Dijkstra算法小根堆每次取距離最小的節點

八、總結:堆的"堆"德

堆的優缺點分析

優點:

  1. 插入/刪除時間復雜度穩定在O(logN)
  2. 獲取極值(堆頂)只需O(1)
  3. 可以高效解決TopK問題
  4. 堆排序是原地排序,空間復雜度O(1)

缺點:

  1. 訪問非堆頂元素效率低(需要遍歷)
  2. 不是穩定排序(相同元素可能換位)
  3. 緩存不友好(數組跳躍訪問)
堆的優點
高效插入刪除
快速獲取極值
解決TopK
原地排序
堆的缺點
非隨機訪問
不穩定
緩存不友好

九、終極對比表:堆 vs 其他數據結構

特性二叉搜索樹跳表哈希表
查找極值O(1)O(logN)O(logN)O(N)
插入/刪除O(logN)O(logN)O(logN)O(1)平均
有序性部分有序(僅堆頂)完全有序完全有序無序
空間復雜度O(N)O(N)O(N)O(N)
實現難度中等中等困難中等
典型應用優先級隊列、TopK范圍查詢、有序數據高性能有序數據結構快速查找、去重

最后的小幽默

程序員的世界里:

  • 當你學會堆:哇!我"堆"數據結構理解好深!
  • 當你寫堆代碼:這bug怎么"堆"了這么多!
  • 當你面試被問堆:面試官,咱們能"堆"心一點嗎?

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/918491.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/918491.shtml
英文地址,請注明出處:http://en.pswp.cn/news/918491.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

嵌入式學習day25

fwrite&#xff1a;fread&#xff1a;fread/fwrite&#xff1a;拷貝圖片&#xff1a;#include <stdio.h>int main(void) {FILE *fsrc NULL;FILE *fdst NULL;char tmpbuff[4096] {0};size_t nret 0;fsrc fopen("src.jpg", "r");if (NULL fsrc){…

2025年中科院2區紅杉優化算法Sequoia Optimization Algorithm-附Matlab免費代碼

1. 簡介 提出了紅杉優化算法&#xff08;SequoiaOA&#xff09;&#xff0c;這是一種受紅杉森林生態系統自我調節動力學和彈性啟發的新型元啟發式方法&#xff0c;不同于傳統的奇異生物學或現象學靈感。開發一個全面的生態系統驅動框架&#xff0c;包括數學建模、系統分析和通過…

【C#】從 Queue 到 ConcurrentQueue:一次對象池改造的實戰心得

背景 最近在做一個圖像處理的 WPF 項目&#xff0c;底層使用 Halcon 的 HObject 來存放圖像。為了減少頻繁創建和釋放對象帶來的開銷&#xff0c;我實現了一個對象池&#xff0c;用來存放 HObject&#xff0c;方便后續流程復用。 最初的實現用的是 .NET 自帶的 Queue<T>&…

深度解析 AS32S601 芯片 CAN Bus Off 機制:從原理到應用的全流程指南

一、前言在汽車電子、工業自動化等眾多領域&#xff0c;CAN 總線作為一種可靠的通信協議被廣泛應用。而 AS32S601 芯片憑借其卓越的性能和可靠性&#xff0c;在這些領域也發揮著重要作用。其中&#xff0c;CAN Bus Off 功能作為 CAN 總線通信中的關鍵錯誤處理機制&#xff0c;對…

PyCharm Community 2024.2.3.exe 安裝教程(詳細步驟,附安裝包下載)

?1. 下載安裝包? 安裝下載地址&#xff1a;https://pan.quark.cn/s/ca11cb817ee5&#xff0c;你已經下載好了 pycharm-community-2024.2.3.exe 這個文件&#xff08;通常是從 JetBrains 官網下的&#xff09;。雙擊這個 .exe 文件開始安裝。 ?2. 開始安裝向導? 雙擊后&am…

JAVA:SpringBoot 集成 Selenium 實現高效爬蟲

?? 1、簡述 在互聯網數據采集中,傳統基于 Jsoup 或 HttpClient 的爬蟲方案面對復雜 JavaScript 渲染頁面時經常力不從心。此時,Selenium WebDriver 提供了更強大的模擬真實瀏覽器行為能力,成為爬取動態網站的利器。 為了繞過反爬機制,結合 IP 代理池 是提升穩定性和并發…

終端安全檢測和防御技術

目錄 1. 終端安全風險 2. 終端安全檢測和防御技術 3. 網關殺毒技術 3.1 計算機病毒工作步驟 3.2 殺毒防御產品 3.3 網關殺毒功能優勢 3.4 網關殺毒實現方式 4.僵尸網絡檢測和防御技術 4.1 僵尸網絡 4.2 僵尸網絡的形成過程&#xff08;APT場景下&#xff09; 4.3 檢測…

Java緩沖流

字節緩沖流&#xff1a;原理&#xff1a;底層自帶長度為8192的緩沖區提高性能拷貝文件一次讀一個字節一次讀一個字節數組字節緩沖流的讀寫原理字符緩沖流&#xff1a;特定方法字符緩沖輸入流基本寫法輸入所有數據字符緩沖流輸出總結

web服務器tomcat內部工作原理以及樣例代碼

目錄 一、Tomcat 運行原理與 Servlet 機制 1、為什么 Java Web 項目需要 Tomcat 2. 進程模式 vs 線程模式 3、Servlet / Controller 是怎么跟 Tomcat 對接的? 4、java反射與代理機制 ※--高級知識點 (1)原理 (1)樣例:用反射和注解模擬 Tomcat 處理 HTTP 請求時,動…

AI賦能IT服務管理:從被動響應到智能驅動的躍遷

過去十年&#xff0c;IT服務管理&#xff08;ITSM&#xff09;經歷了從紙質工單到數字化平臺的變革&#xff0c;但無論工具多么先進&#xff0c;大多數IT團隊依然面臨著相同的困境&#xff1a;事件處理速度跟不上業務變化人工重復操作占用大量時間數據雖多&#xff0c;卻缺乏可…

云計算-K8s 核心組件之CronJob、RBAC、HPA ,LimitRange、DaemonSet、nodeSelector如何作戰?

目錄 1.CronJob管理 2.RBAC管理 3.HPA管理 4.健康檢查 5.LimitRange管理 6.DaemonSet管理 7.nodeSelector管理 簡介 1. CronJob&#xff08;定時任務控制器&#xff09; 按固定時間間隔&#xff08;類似 Linux cron&#xff09;自動觸發一次性任務&#xff08;Job&#…

數據分析學習總結之實例練習(雙十一淘寶美妝)

本次通過對雙十一淘寶美妝數據的分析實踐&#xff0c;我系統掌握了數據處理與分析的完整流程&#xff0c;從數據初步認知到深度挖掘&#xff0c;再到可視化呈現與結論提煉&#xff0c;收獲頗豐。以下是具體的學習總結&#xff1a;一、數據初步了解&#xff1a;奠定分析基礎在分…

如何評估一個需求的業務價值

要科學、全面地評估一個需求的業務價值&#xff0c;核心在于建立一個多維度的、從戰略到財務、從客戶到風險的“價值羅盤”&#xff0c;并運用這套羅盤&#xff0c;對需求進行系統性的、數據驅動的量化與定性分析。一套成熟的價值評估體系&#xff0c;其構建必須涵蓋五大關鍵視…

day38_2025-08-12

一、 圖像數據的介紹 1.1 灰度圖像 從這里開始我們進入到了圖像數據相關的部分&#xff0c;也是默認你有之前復試班計算機視覺相關的知識&#xff0c;但是一些基礎的概念我仍然會提。 昨天我們介紹了minist這個經典的手寫數據集&#xff0c;作為圖像數據&#xff0c;相較于結構…

Kubernetes1.28-單Master集群部署

一、 服務器環境及初始化 1、架構分析 集群角色主機名操作系統IP地址masterk8s-masterOpenEuler24.03192.168.166.128nodek8s-node1OpenEuler24.03192.168.166.129nodek8s-node2OpenEuler24.03192.168.166.130 2、初始化 所有節點都需要初始化&#xff01; 2.1、清空Iptal…

使用pyqt5實現可勾選的測試用例界面

目錄 界面 代碼 python有哪些自動化測試的庫和html的報告的庫可以和這個軟件結合使用的 **一、自動化測試核心庫** **二、HTML報告生成庫** **三、其他實用工具** **與您的工具結合建議** 參考 界面 代碼 import sys import time import random from PyQt5.QtWidgets import (…

C語言變量的聲明和定義有什么區別?

定義&#xff1a;定義&#xff1a;為變量分配地址和存儲空間聲明&#xff1a;不分配地址和存儲空間一個變量可以在多個地方聲明&#xff0c;但是只在一個地方定義。加入extern修飾的是變量的聲明&#xff0c;說明此變量將在文件或在文件后面部分定義。1.變量聲明作用&#xff1…

imx6ull-驅動開發篇20——linux互斥體實驗

目錄 實驗程序編寫 修改設備樹文件 LED 驅動修改 mutex.c 測試mutexApp.c Makefile 文件 運行測試 在之前的文章里&#xff0c;我們學習了&#xff1a;驅動開發篇16——信號量與互斥體。 本講實驗里&#xff0c;我們來使用互斥體mutex實現 LED 燈互斥訪問的功能&#x…

[4.2-2] NCCL新版本的register如何實現的?

文章目錄1->2->31. ncclRegisterP2pIpcBuffer2. ncclIpcLocalRegisterBuffer(..., 1, 0,...)3. ipcRegisterBuffer(..., regRecord,..., isLegacyIpc)4. p2pProxyRegister()1->2->3 1. ncclRegisterP2pIpcBuffer 在enqueue.cc內的調用是&#xff1a; NCCLCHECK(…

在idea中git切換分支,但是我的文件沒add,沒commit

這是一個很悲傷的故事&#xff0c;我朋友一個下午寫了4個小時的代碼&#xff0c;差不多10多個類&#xff0c;都在切換分支的時候。IDEA發現有沖突&#xff0c;然后就要resolve conflict&#xff0c;發現自己不知道怎么操作&#xff0c;就點了abort & rollback。然后所有代碼…