堆的理論知識

1 引入

1.1?普通二叉樹不適合用數組存儲的原因

普通二叉樹的結構是 “不規則” 的 —— 節點的左右孩子可能缺失,且缺失位置無規律。
若用數組存儲(按 “層次遍歷順序” 分配索引,即根節點放索引 0,根的左孩子放 1、右孩子放 2,以此類推),缺失的節點會導致數組中出現大量空位置,造成空間浪費。

例如:一棵只有 “右孩子” 的二叉樹(根→右→右→...),按數組存儲時,所有左孩子的位置(索引 1、3、7...)都會空著,這些空位置就是無效浪費。

1.2?完全二叉樹適合順序存儲的原因

完全二叉樹的結構是 “緊湊” 的:

  • 除最后一層外,其他層的節點均 “滿”(即每個節點都有左右孩子);
  • 最后一層的節點從左到右 “連續排列”,沒有中間缺失。

這種結構使得按層次遍歷順序存儲時,數組的索引與節點位置完全對應,幾乎沒有空位置。例如:一個高度為 3 的完全二叉樹(共 7 個節點),數組索引 0-6 會被完全填滿,無任何浪費。

1.3?堆用數組存儲的合理性

堆是一種 “特殊的完全二叉樹”(滿足 “大頂堆” 或 “小頂堆” 特性:大頂堆中每個父節點的值≥子節點,小頂堆則≤)。

由于堆本質是完全二叉樹,自然繼承了 “緊湊結構” 的特點,因此適合用數組存儲。

數組存儲堆時,通過索引可快速定位節點的父 / 子節點,規則為(假設節點在數組中索引為i):

  • 左孩子索引:2i + 1
  • 右孩子索引:2i + 2
  • 父節點索引:(i - 1) // 2(整數除法)。

這種對應關系讓堆的核心操作(如 “堆化”“插入”“刪除”)能通過數組索引高效實現,無需額外存儲指針,既省空間又提效。

1.4. “數據結構的堆” 與 “操作系統的堆” 的區分

兩者僅名稱相同,本質完全無關:

  • 數據結構的堆:是一種特殊的完全二叉樹,用于實現優先隊列(如任務調度中的 “最高優先級先執行”),核心特性是 “父節點與子節點的大小關系固定”(大頂 / 小頂)。
  • 操作系統的堆:是內存中的一塊區域(與 “棧” 相對),用于 “動態內存分配”(如 C 語言malloc、Javanew申請的內存均來自這里),由操作系統的內存管理模塊負責分配與回收。

所以,綜上所述:

堆是一種特殊的完全二叉樹(滿足大頂堆或小頂堆特性),而它的實現依賴于 “順序存儲”(數組)—— 這與二叉樹的存儲特性直接相關。

普通二叉樹因結構不規則,用數組存儲會產生大量空位置(例如僅右孩子存在時,左孩子的索引全為空),空間效率極低;但完全二叉樹不同,其節點按層次緊湊排列,無無規律缺失,用數組存儲時索引可與節點位置一一對應,幾乎無空間浪費。

堆作為完全二叉樹的 “特例”,天然適配數組存儲:我們將堆的節點按層次遍歷順序存入數組,通過索引規則(左孩子2i+1、右孩子2i+2、父節點(i-1)//2)可快速定位任意節點的父子關系。這種存儲方式讓堆的核心操作能通過數組索引直接計算,無需指針,既簡化實現又提升效率(時間復雜度為 O (log n))。

需特別注意:此處的 “堆” 是數據結構概念,與操作系統中 “管理動態內存的堆區域” 完全無關 —— 前者是一種二叉樹后者內存分段,僅名稱巧合。

2 堆的概念

堆是一種特殊的完全二叉樹,分為:

  • 大根堆:每個節點的值≥其左右孩子的值,根最大。
  • 小根堆:每個節點的值≤其左右孩子的值,根最小。

小堆不一定是升序,大堆不一定是降序,所以,成為堆并不代表有序。?

3 堆的經典選擇題辨析

堆作為一種特殊的完全二叉樹,其結構特性(大頂堆 / 小頂堆)和存儲方式(數組順序存儲)決定了它在算法中的高頻應用。本文通過 4 道經典題目,從堆的判斷、刪除重建、初始堆構建到調整過程,帶你深入理解堆的核心邏輯。

3.1 判斷下列關鍵字序列是否為堆

題目:下列關鍵字序列為堆的是()
A 100,60,70,50,32,65
B 60,70,65,50,32,100
C 65,100,70,32,50,60
D 70,65,100,32,50,60
E 32,50,100,70,65,60
F 50,100,70,65,60,32

解析:堆的核心判斷標準

堆分為大頂堆(每個父節點的值≥子節點)和小頂堆(每個父節點的值≤子節點),判斷序列是否為堆,需驗證所有父節點與子節點的關系是否滿足其一。

數組存儲堆時,節點索引關系為(設節點索引為i):

  • 左孩子:2i+1,右孩子:2i+2

選項 A 分析:100,60,70,50,32,65

  • 根節點(i=0):100,左孩子(i=1)=60,右孩子(i=2)=70 → 100≥60 且 100≥70(滿足大頂堆父節點要求);
  • 節點 i=1(60):左孩子(i=3)=50,右孩子(i=4)=32 → 60≥50 且 60≥32;
  • 節點 i=2(70):左孩子(i=5)=65 → 70≥65;
    所有父節點均滿足 “≥子節點”,是大頂堆

其他選項均不滿足:

  • 選項 B:根節點 60 的右孩子 100>60,不滿足大頂堆;
  • 選項 C:節點 i=1(100)的右孩子(i=4)=50,左孩子(i=3)=32,但根節點 65<100,不滿足大頂堆;
  • 其余選項同理可證不滿足堆的定義。

答案:A

3.2 小根堆刪除堆頂后重建的比較次數

題目:已知小根堆為 8,15,10,21,34,16,12,刪除關鍵字 8 之后需重建堆,比較次數是()。
A 1 B 2 C 3 D 4

解析:小根堆的刪除與重建流程

小根堆刪除堆頂(最小值)的步驟:

  1. 替換堆頂:用最后一個元素替換堆頂(保證結構緊湊);
  2. 向下調整:從新堆頂開始,與左右孩子中較小的節點比較,若不滿足 “父≤子” 則交換,重復至平衡。

具體步驟:

原堆(數組):[8,15,10,21,34,16,12](長度 7,索引 0-6)

  • 刪除堆頂 8 后,用最后一個元素 12 替換堆頂,新數組為[12,15,10,21,34,16](長度 6,索引 0-5);
  • 向下調整 12(堆頂):
    • 左孩子(i=1)=15,右孩子(i=2)=10 → 較小的孩子是 10(i=2);
    • 比較 12 與 10:12>10,交換 → 數組變為[10,15,12,21,34,16]
    • 調整 12(現在在 i=2):左孩子(i=5)=16,右孩子無;
    • 比較 12 與 16:12<16,無需交換,調整結束。

比較次數統計:

  • 第一次:12 與左孩子 15、右孩子 10 比較(2 次);
  • 第二次:12 與左孩子 16 比較(1 次);
    共 3 次比較。

答案:C

3.3 堆排序的初始堆構建

題目:一組記錄排序碼為 (5,11,7,2,3,17),利用堆排序方法建立的初始堆為()
A(11,5,7,2,3,17) B(11,5,7,2,17,3) C(17,11,7,2,3,5) D(17,11,7,5,3,2) E(17,7,11,3,5,2) F(17,7,11,3,2,5)

解析:堆排序的初始堆(大頂堆)構建

堆排序的第一步是構建大頂堆(根節點為最大值),步驟:

  1. 從最后一個非葉子節點開始(索引(n-1)//2),依次向前調整;
  2. 調整規則:若父節點<子節點中較大值,則交換,并遞歸調整交換后的子節點。

具體步驟:

排序碼:[5,11,7,2,3,17](長度 6,索引 0-5)

  • 最后一個非葉子節點索引:(6-1)//2=2(值為 7);
    • 節點 i=2(7)的右孩子 i=5(17)→ 7<17,交換 → 數組變為[5,11,17,2,3,7]
  • 前一個非葉子節點 i=1(11):左孩子 i=3(2),右孩子 i=4(3)→ 11≥兩者,無需調整;
  • 第一個非葉子節點 i=0(5):左孩子 i=1(11),右孩子 i=2(17)→ 5<17,交換 → 數組變為[17,11,5,2,3,7]
  • 調整交換后 i=2(5):右孩子 i=5(7)→ 5<7,交換 → 數組變為[17,11,7,2,3,5],此時所有父節點均滿足大頂堆規則。

答案:C

3.4 最小堆刪除堆頂后的結果

題目:最小堆 [0,3,2,5,7,4,6,8],在刪除堆頂元素 0 之后,其結果是()
A[3,2,5,7,4,6,8] B[2,3,5,7,4,6,8] C[2,3,4,5,7,8,6] D[2,3,4,5,6,7,8]

解析:最小堆的刪除與調整

最小堆刪除堆頂(最小值)的流程與題目 2 一致:替換堆頂→向下調整(保證父≤子)。

具體步驟:

原堆:[0,3,2,5,7,4,6,8](長度 8,索引 0-7)

  • 刪除 0 后,用最后一個元素 8 替換堆頂 → 新數組[8,3,2,5,7,4,6](長度 7,索引 0-6);
  • 向下調整 8(堆頂):
    • 左孩子 i=1(3),右孩子 i=2(2)→ 較小孩子是 2(i=2);
    • 8>2,交換 → 數組變為[2,3,8,5,7,4,6]
  • 調整 8(i=2):
    • 左孩子 i=5(4),右孩子 i=6(6)→ 較小孩子是 4(i=5);
    • 8>4,交換 → 數組變為[2,3,4,5,7,8,6]
  • 8(i=5)無孩子,調整結束。

答案:C

?

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

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

相關文章

【python實用小腳本-161】Python Json轉Xml:告別手敲標簽——一行命令把配置秒變可導入的XML

Python Json轉Xml:告別手敲標簽——一行命令把配置秒變可導入的XML 關鍵詞:json轉xml、零依賴腳本、自動生成標簽、小白友好、跨平臺故事開場:周五下午,老板又甩來“配置翻譯”任務 17:55,你正準備關機,老板…

WisFile(文件整理工具) v1.2.19 免費版

下載:https://pan.quark.cn/s/db99b679229fWisFile是一款免費AI文件管理工具,可以在電腦本地運行。它專注于解決文件命名混亂、歸類無序和手動整理耗時的問題。通過AI技術智能識別文件內容,支持批量重命名和智能分類歸檔功能,可自…

簡歷美容院:如何把“打雜經歷“包裝成“核心項目“?

簡歷美容院:如何把"打雜經歷"包裝成"核心項目"? 大家好,我是程序員小白條,今天來研究下簡歷包裝的事,小白可以按我的包裝流程走,可以分步驟進行包裝,具體怎么進行可以看正文…

零基礎-動手學深度學習-7.7 稠密連接網絡(DenseNet)

ResNet極大地改變了如何參數化深層網絡中函數的觀點。 稠密連接網絡(DenseNet)在某種程度上是ResNet的邏輯擴展。讓我們先從數學上了解一下。 7.7.1. 從ResNet到DenseNet 7.7.2. 稠密塊體 DenseNet使用了ResNet改良版的“批量規范化、激活和卷積”架構…

Marin說PCB之POC電路layout設計仿真案例---09

好消息,好消息,小編最愛的國漫凡人修仙傳電視劇版本的終于可以看了,小編我推薦一波啊,感興趣的道友們可以去某酷視頻去追劇啊。 好了,咱們言歸正傳啊。本期的案例是這個月中旬我們組的測試大哥阿永去某田實驗室去測試我…

論文閱讀--射頻電源在半導體領域的應用

《射頻電源在半導體領域的應用》 論文信息:左政,馮國楠,李建慧,等.射頻電源在半導體領域的應用[J].軟件和集成電路,2025,(04):38-43.DOI:10.19609/j.cnki.cn10-1339/tn.2025.04.007. 一、射頻電源的定義與分類 1.1 定義射頻電源(RF Power Supply&#xf…

綠算技術攜手昇騰發布高性能全閃硬盤緩存設備,推動AI大模型降本增效

在數字化浪潮席卷全球的今天,人工智能已經成為推動企業創新與發展的重要力量。廣東省綠算技術有限公司(簡稱“綠算技術”)緊跟時代步伐,基于華為昇騰AI大模型,推出了高性能全閃硬盤緩存設備,致力于為人工智…

HoloLens2系列講解 - 06 基本操作

一、導入MRTK插件 1. 首先要新建一個項目,打開unity,新建一個project。 2. 導入MRTK包。 3. 點擊 Mixed Reality Toolkit > Add to scene and Configure 添加MR場景配置文件。

Linux Vim 編輯器使用指南

Linux Vim 編輯器使用指南一、Vim 簡介 Vim(Vi IMproved)是 Linux/Unix 系統中最流行的文本編輯器之一,它是 Vi 的增強版,支持多模式操作、語法高亮、插件擴展等特性,無需鼠標即可高效編輯文本。 二、核心工作模式 Vim…

運維筆記:破解 VMware 遷移難題

一、VMware 遷移前的準備與評估1.1 遷移場景與目標分析VMware 遷移常見場景包括:同平臺升級:從 vSphere 6.7 遷移到 7.0/8.0(硬件兼容、功能迭代)跨平臺遷移:VMware→KVM/Xen(降低 licensing 成本&#xff…

cartographer 點云數據的預處理

目錄 傳感器數據的走向 體素濾波與之后的處理 3D情況下的激光雷達數據的預處理 初始位姿估計 位姿推測器的優缺點分析與總結 可能有問題的點 可能的改進建議 傳感器數據的走向 傳感器數據從CollatedTrajectoryBuilder類的HandleCollatedSensorData函數 傳遞GlobalTrajec…

基于數據挖掘的短視頻點贊影響因素分析【LightGBM、XGBoost、隨機森林、smote】

文章目錄有需要本項目的代碼或文檔以及全部資源,或者部署調試可以私信博主項目介紹總結每文一語有需要本項目的代碼或文檔以及全部資源,或者部署調試可以私信博主 項目介紹 隨著短視頻行業的高速發展,尤其是以抖音為代表的平臺不斷壯大&…

Git 從入門到精通

Git 從入門到精通 涵蓋了核心概念、常用命令、協作流程和高級技巧: 核心理念: 版本控制: 記錄文件變化歷史,可回溯到任意版本。分布式: 每個開發者擁有完整的倉庫副本(包括完整歷史)&#xf…

UE5多人MOBA+GAS 30、技能升級機制

文章目錄前言技能的升級修改一下按鍵的輸入判斷是否滿級在ASC中升級技能由角色的輸入調用ASC的升級功能技能圖標的優化技能升級材質,可升級技能圖標的閃爍刷新技能升級后的藍耗和CD,以及藍不夠時技能進入灰色狀態修復傷害數字特效只顯示3位數的問題前言 …

筆試——Day22

文章目錄第一題題目思路代碼第二題題目:思路代碼第三題題目:思路代碼第一題 題目 添加字符 思路 枚舉所有字符串a與字符串b相對應的位置 代碼 第二題 題目: 數組變換 思路 貪心 以最大值為基準元素,判斷其他元素能否變為最…

__getattr__和 __getattribute__ 的用法

1、__getattr__ 的用法當實例對象訪問一個不存在的屬性時,會執行 __getattr__ 方法,如果屬性存在的話,就不會執行案例 class Person:def __init__(self, name, age):self.name nameself.age agedef get_info(self):return f"name: {se…

信息化項目驗收測試實戰指南

在當今數字化轉型的大背景下,信息化項目驗收建設已成為企業提升運營效率、優化管理流程的重要手段。然而,很多企業在投入大量資金建設信息系統后,卻常常面臨系統上線后無法滿足實際業務需求的困境。究其原因,往往是由于忽視了信息…

牛頓拉夫遜法PQ分解法計算潮流MATLAB程序計算模型。

牛頓拉夫遜法&PQ分解法計算潮流MATLAB程序計算模型。本程序模型基于MATLAB進行潮流計算,建議先安裝matpower插件(MATLAB中非常重要的潮流計算的插件)。本程序可進行牛拉法和PQ分解法潮流計算的切換,對比潮流計算的結果。很適合…

Go語言實戰案例-計算字符串編輯距離

在自然語言處理、拼寫糾錯、模糊搜索等場景中,我們經常需要衡量兩個字符串之間的相似度。編輯距離(Edit Distance) 就是一個經典的衡量方式,它描述了將一個字符串轉換為另一個字符串所需的最少操作次數。 一、問題定義:什么是編輯距離? 編輯距離,也稱為 Levenshtein Di…

Java時間與日期常用方法

DateDate date new Date(); //獲取當前時間 System.out.println(date.getYear() 1900); // 必須加上1900 System.out.println(date.getMonth() 1); // 0~11,必須加上1 System.out.println(date.getDate()); // 1~31,不能加1Ca…