高級堆結構

一、二項堆(Binomial Heap):理解「合并操作」的優化

二項堆的核心優勢是高效合并,類似 “二進制加法”。我們通過「合并兩個二項堆」的偽代碼和步驟來理解:

核心結構偽代碼:
class BinomialTreeNode:def __init__(self, key):self.key = key  # 節點值self.degree = 0  # 度數(子節點數量)self.parent = None  # 父節點self.children = []  # 子節點列表(按度數從小到大排列)class BinomialHeap:def __init__(self):self.trees = []  # 存儲二項樹(按度數從小到大排序,每個度數最多1棵)self.min_node = None  # 指向最小元素節點
關鍵操作:合并兩個二項堆(類似二進制加法)
def merge_heaps(h1, h2):# 1. 合并兩個堆的樹列表(按度數從小到大)merged = []i = j = 0while i < len(h1.trees) and j < len(h2.trees):t1 = h1.trees[i]t2 = h2.trees[j]if t1.degree < t2.degree:merged.append(t1)i += 1else:merged.append(t2)j += 1merged.extend(h1.trees[i:])merged.extend(h2.trees[j:])# 2. 合并相同度數的樹(類似二進制進位)result = BinomialHeap()carry = None  # 用于暫存合并后的樹for tree in merged:if carry is None:carry = treeelse:if carry.degree == tree.degree:# 合并兩棵同度數的樹(小根作為父節點)if carry.key > tree.key:carry, tree = tree, carry  # 保證carry是小根tree.parent = carrycarry.children.append(tree)carry.degree += 1  # 度數+1else:# 度數不同,直接加入結果result.trees.append(carry)carry = treeif carry is not None:result.trees.append(carry)# 3. 更新最小節點result.update_min()return result
步驟拆解(合并示例):

假設?h1?有一棵樹?B2(度數 2),h2?有一棵樹?B2(度數 2):

  1. 合并樹列表后,得到兩個度數為 2 的樹。
  2. 合并這兩棵樹:較小根節點作為父,另一棵作為子,得到一棵?B3(度數 3)。
  3. 最終結果堆只包含?B3,完成合并。

核心理解:二項堆的合并像 “二進制加法”,同度數樹合并后度數 + 1,效率遠高于二叉堆的 O (n) 合并。

二、斐波那契堆(Fibonacci Heap):理解「延遲操作」

斐波那契堆的高效源于 “不立即處理沖突,延遲到必要時”。以「插入」和「提取最小」為例:

核心結構偽代碼:
class FibonacciNode:def __init__(self, key):self.key = keyself.parent = Noneself.children = []  # 子節點列表self.degree = 0  # 子節點數量self.marked = False  # 標記:是否失去過子節點class FibonacciHeap:def __init__(self):self.root_list = []  # 根節點列表(所有樹的根)self.min_node = None  # 最小節點指針self.node_count = 0  # 總節點數
1. 插入操作(O (1),體現延遲思想):
def insert(self, key):new_node = FibonacciNode(key)self.root_list.append(new_node)  # 直接加入根列表,不合并# 更新最小節點if self.min_node is None or new_node.key < self.min_node.key:self.min_node = new_nodeself.node_count += 1

步驟理解:插入時直接把新節點作為一棵新樹加入根列表,不處理任何合并,所以是 O (1)。

2. 提取最小節點(觸發延遲處理,攤還 O (log n)):
def extract_min(self):if self.min_node is None:return None# 1. 把最小節點的子節點加入根列表(失去父節點)for child in self.min_node.children:self.root_list.append(child)child.parent = None# 2. 從根列表移除最小節點self.root_list.remove(self.min_node)self.node_count -= 1# 3. 延遲處理:合并相同度數的樹(此時才清理結構)self.consolidate()  # 核心:合并根列表中同度數的樹# 4. 重新找最小節點self.min_node = self.find_min_in_root_list()return self.min_node.key

步驟理解:只有提取最小節點時,才會合并根列表中同度數的樹(類似二項堆的合并),這個操作的代價被 “攤還” 到之前的插入操作上,所以整體攤還復雜度是 O (log n)。

核心理解:斐波那契堆通過 “延遲合并” 把復雜操作推遲,讓簡單操作(插入、合并)變得極快。

三、配對堆(Pairing Heap):理解「簡單高效的合并」

配對堆的核心是極簡的結構兩兩合并策略,實現簡單卻高效。

核心結構偽代碼:
class PairingNode:def __init__(self, key):self.key = keyself.children = []  # 子節點列表(子堆)class PairingHeap:def __init__(self, key=None):self.root = PairingNode(key) if key is not None else None
1. 合并操作(O (1),體現簡單性):
def merge(h1, h2):# 比較兩個根,小根作為父節點,大根作為子節點if h1 is None:return h2if h2 is None:return h1if h1.root.key > h2.root.key:h1, h2 = h2, h1  # 保證h1根更小# 把h2作為h1的子節點h1.root.children.append(h2.root)return h1

步驟理解:合并兩個配對堆時,只需把根更大的堆作為子節點掛到根更小的堆上,一步完成,所以是 O (1)。

2. 提取最小節點(用 “配對法” 合并子堆):
def extract_min(self):if self.root is None:return Nonemin_key = self.root.key# 合并所有子節點(核心:配對法)if self.root.children:self.root = self.pairwise_merge(self.root.children)else:self.root = Nonereturn min_keydef pairwise_merge(children):# 第一步:兩兩合并子節點if len(children) == 0:return Noneif len(children) == 1:return children[0]# 兩兩合并,遞歸處理剩余merged = []for i in range(0, len(children)-1, 2):merged_child = merge(children[i], children[i+1])merged.append(merged_child)# 若有奇數個,最后一個單獨處理if len(children) % 2 == 1:merged.append(children[-1])# 第二步:依次合并結果return pairwise_merge(merged)

步驟理解:提取最小節點(根節點)后,將其子節點兩兩合并,再遞歸合并結果,確保合并效率。這種 “配對合并” 策略讓攤還復雜度接近 O (log n)。

核心理解:配對堆用最簡單的結構(單根 + 子堆列表)和合并策略,在實踐中比理論更高效,適合工程實現。

總結:通過核心操作理解高級堆

堆類型最能體現特性的操作操作邏輯核心為什么高效?
二項堆合并按度數從小到大合并,同度數樹合并為更高一度樹(類似二進制加法)合并復雜度從 O (n) 降為 O (log n)
斐波那契堆插入直接加入根列表,不合并(延遲處理)簡單操作 O (1),復雜操作攤還處理
配對堆合并小根作為父,大根作為子,提取時兩兩合并子堆結構極簡,合并邏輯簡單,常數小

對于初學者,不需要死記代碼,重點理解:

  • 二項堆是 “有序合并的基礎”;
  • 斐波那契堆是 “延遲優化的極致”;
  • 配對堆是 “簡單實用的優選”。

它們的設計思想(如延遲操作、結構化合并)對理解更復雜的算法非常有幫助。

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

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

相關文章

系統學習算法 專題十七 棧

題目一&#xff1a;算法思路&#xff1a;一開始還是暴力解法&#xff0c;即遍歷字符串&#xff0c;如果出現當前位置的字符等于后面的字符&#xff0c;則刪除這兩個字符&#xff0c;然后再從頭遍歷&#xff0c;如此循環即可但是這樣時間復雜度很高&#xff0c;每刪除一次就從頭…

深入解析函數指針及其數組、typedef關鍵字應用技巧

目錄 一、函數指針變量的創建 1、什么是函數指針變量&#xff1f; 2、函數是否有地址&#xff1f; 3、創建函數指針變量 4、函數指針類型解析 二、函數指針變量的使用 三、兩段有趣的代碼 1、解釋 (*(void (*)())0)(); 2、解釋 void (*signal(int, void(*)(int)))(int…

k8s集群搭建一主多從的jenkins集群

方案 --------------------- | Jenkins Master | | - 持久化配置 |<---(hostpath 存儲) | - 自動容災 | --------------------|| Jenkins JNLP 通信| ----------v---------- ------------------- | Jenkins Agent | | Kubernetes Pl…

重溫k8s基礎概念知識系列三(工作負載)

文章目錄1、工作負載簡述2、Deployment1.1、創建 Deployment1.2、檢查 Deployment上線狀態3、StatefulSet4、DaemonSet3.1、創建 DaemonSet3.2、運行DaemonSet5、Job5.1、運行示例 Job5.2、檢查 Job 的狀態6、CronJob上一節&#xff0c;我們復習了Pod相關知識&#xff0c;大多情…

開源 Arkts 鴻蒙應用 開發(十八)通訊--Ble低功耗藍牙服務器

文章的目的為了記錄使用Arkts 進行Harmony app 開發學習的經歷。本職為嵌入式軟件開發&#xff0c;公司安排開發app&#xff0c;臨時學習&#xff0c;完成app的開發。開發流程和要點有些記憶模糊&#xff0c;趕緊記錄&#xff0c;防止忘記。 相關鏈接&#xff1a; 開源 Arkts …

Go語言并發編程 ------ 鎖機制詳解

Go語言提供了豐富的同步原語來處理并發編程中的共享資源訪問問題。其中最基礎也最常用的就是互斥鎖&#xff08;Mutex&#xff09;和讀寫鎖&#xff08;RWMutex&#xff09;。1. sync.Mutex&#xff08;互斥鎖&#xff09;Mutex核心特性互斥性/排他性&#xff1a;同一時刻只有一…

8月17日星期天今日早報簡報微語報早讀

8月17日星期天&#xff0c;農歷閏六月廿四&#xff0c;早報#微語早讀。1、《南京照相館》領跑&#xff0c;2025年暑期檔電影總票房破95億&#xff1b;2、神舟二十號圓滿完成第三次出艙任務&#xff1b;3、宇樹G1人形機器人100米障礙賽再奪金牌&#xff1b;4、廣東佛山新增報告基…

在QML中使用Chart組件

目錄前言1. 如何安裝 Chart 組件2. 創建 QML 工程時的常見問題3. 解決方案&#xff1a;改用 QApplication QQuickView修改主函數&#xff08;main.cpp&#xff09;4. QApplication 與 QGuiApplication 的差異為什么 Qt Charts 需要 QApplication&#xff1f;總結示例下載前言 …

【P40 6-3】OpenCV Python——圖像融合(兩張相同屬性的圖片按比例疊加),addWeighted()

P40 6-3 文章目錄import cv2 import numpy as npback cv2.imread(./back.jpeg) smallcat cv2.imread(./smallcat1.jpeg)#只有兩張圖的屬性是一樣的才可以進行溶合 print(back.shape) print(smallcat.shape)result cv2.addWeighted(smallcat, 0.7, back, 0.3, 0) cv2.imshow(…

傳輸層協議 TCP(1)

傳輸層協議 TCP&#xff08;1&#xff09; TCP 協議 TCP 全稱為 “傳輸控制協議(Transmission Control Protocol”). 人如其名, 要對數據的傳輸進行一個詳細的控制; TCP 協議段格式 ? 源/目的端口號: 表示數據是從哪個進程來, 到哪個進程去; ? 32 位序號/32 位確認號: 后面詳…

黎陽之光:以動態感知與 AI 深度賦能,引領電力智慧化轉型新革命

當全球能源結構加速向清潔低碳轉型&#xff0c;新型電力系統建設成為國家戰略核心&#xff0c;電力行業正經歷從傳統運維向智慧化管理的深刻變革。2024 年《加快構建新型電力系統行動方案》明確提出&#xff0c;到 2027 年需建成全國智慧調度體系&#xff0c;實現新能源消納率突…

自動駕駛中的傳感器技術34——Lidar(9)

補盲lidar設計&#xff1a;機械式和半固態這里不再討論&#xff0c;這里主要針對全固態補盲Lidar進行討論1、系統架構設計采用Flash方案&#xff0c; 設計目標10m10%&#xff0c;實現30m距離的點云覆蓋&#xff0c;同時可以驗證不同FOV鏡頭的設計下&#xff0c;組合為多款產品。…

Originality AI:原創度和AI內容檢測工具

本文轉載自&#xff1a;Originality AI&#xff1a;原創度和AI內容檢測工具 - Hello123工具導航 ** 一、AI 內容誠信管理專家 Originality AI 是面向內容創作者的全棧式質量檢測平臺&#xff0c;整合 AI 內容識別、抄襲查驗、事實核查與可讀性分析四大核心功能&#xff0c;為…

OpenCV圖像平滑處理方法詳解

引言 在數字圖像處理中&#xff0c;圖像平滑是一項基礎而重要的預處理技術。它主要用于消除圖像中的噪聲、減少細節層次&#xff0c;為后續的圖像分析&#xff08;如邊緣檢測、目標識別等&#xff09;創造更好的條件。OpenCV作為最流行的計算機視覺庫之一&#xff0c;提供了多種…

每天兩道算法題:DAY1

題目一&#xff1a;金幣 題目一&#xff1a;金幣 1.題目來源&#xff1a; NOIP2015 普及組 T1&#xff0c;難度紅色&#xff0c;入門簽到題。 2.題目描述&#xff1a; 3.題目解析&#xff1a; 問題轉化&#xff1a;求下面的一個數組的前 k 項和。 4.算法原理&#xff1a; …

C++核心語言元素與構建塊全解析:從語法規范到高效設計

&#x1f4cc; 為什么需要雙維度學習C&#xff1f;核心語言元素 → 掌握標準語法規則&#xff08;避免未定義行為Undefined behavior&#xff09;構建塊&#xff08;Building Blocks&#xff09; → 像搭積木一樣組合功能&#xff08;提升工程能力&#xff09; 例如&#xff1a…

RK3588開發板Ubuntu系統燒錄

Ubuntu22.04——YOLOv8模型訓練到RK3588設備部署和推理 文章中給出了通過ARM設備上面的NPU進行深度學習的模型推理過程,在此之前,我們在收到一塊全新的rk3588開發板后,需要對其進行系統的燒錄,這里以Ubuntu22.04系統為例。 目錄 1.獲取待燒錄系統的鏡像 2.燒錄工具準備 2.1…

AI評測的科學之道:當Benchmark遇上統計學

AI評測的科學之道&#xff1a;當Benchmark遇上統計學 —— 如何客觀評估大模型能力&#xff0c;避免落入數據陷阱 在人工智能尤其是大語言模型&#xff08;LLU&#xff09;爆發式發展的今天&#xff0c;各類模型榜單&#xff08;如Open LLM Leaderboard、LMSys Arena&#xff0…

CSS 基礎入門教程:從零開始學習樣式表

一、CSS 簡介CSS&#xff08;Cascading Style Sheets&#xff0c;層疊樣式表&#xff09;是一種用于描述 HTML 或 XML 等文檔呈現方式的語言。它是現代網頁設計的三大核心技術之一&#xff0c;與HTML&#xff08;結構層&#xff09;和JavaScript&#xff08;行為層&#xff09;…

圖解簡單選擇排序C語言實現

1 簡單選擇排序 簡單選擇排序&#xff08;Simple Selection Sort&#xff09;是一種基礎且直觀的排序算法&#xff0c;其核心思想是通過重復選擇未排序部分中的最小&#xff08;或最大&#xff09;元素&#xff0c;并將其放到已排序部分的末尾&#xff0c;逐步完成整個序列的排…