《紅黑樹實現》

引言:

上次我們學習了比二叉搜索樹更高效的平衡二叉搜索樹(AVL樹),這次我們要學習的是另外一種對二叉搜索樹的優化后的紅黑樹

一:紅黑樹概念:

紅黑樹是一棵二叉搜索樹,他的每個結點增加一個存儲位來表示結點的顏色,可以是紅色或者黑色。通過對任何一條從根到葉子的路徑上各個結點的顏色進行約束,紅黑樹確保沒有一條路徑會比其他路徑長出2倍,因而是接近平衡的。

(1)紅黑樹規則:

  1. 每個結點不是紅色就是黑色。
  2. 根結點是黑色的。
  3. 如果一個結點是紅色的,則它的兩個孩子結點必須是黑色的,也就是說任意一條路徑不會有連續的紅色結點。
  4. 對于任意一個結點,從該結點到其所有NULL結點的簡單路徑上,均包含相同數量的黑色結點。

(2)思考:紅黑樹是如何確保最長路徑不超過最短路徑的2倍的?

  1. 由規則4可知,從根到NULL結點的每條路徑都有相同數量的黑色結點,所以極端場景下,最短路徑就就是全是黑色結點的路徑,假設最短路徑長度為bh(black height)
  2. 由規則2和規則3可知,任意一條路徑不會有連續的紅色結點,所以極端場景下,最長的路徑就是一黑一紅間隔組成,那么最長路徑的長度為2*bh
  3. 綜合紅黑樹的4點規則而言,理論上的全黑最短路徑和一黑一紅的最長路徑并不是在每棵紅黑樹都存在的。假設任意?條從根到NULL結點路徑的長度為x,那么bh <= h <= 2*bh

(3)紅黑樹效率:

假設N是紅黑樹中節點的數量,h為最短路徑的長度,那么2^h - 1 <= N < 2 ^ (2 * h) - 1 ,由此推出h ≈ logN ,也就是意味著紅黑樹的增刪查改最壞情況下也就是走最長路徑時的效率也是logN
但紅黑樹的表達相對于AVL樹要抽象一些,AVL樹是通過高度差來直觀地控制,紅黑樹通過4條規則的顏色約束,間接實現了近似平衡,他們效率都是同一檔次,但是相對而言,插入相同數量的結點,紅黑樹的旋轉次數是更少的,因為他對平衡的控制沒那么嚴格。

在這里插入圖片描述

二:紅黑樹的實現

1. 紅黑樹的結構:

跟前面實現的AVL樹相比,紅黑樹的結構只是將平衡因子變為了顏色記錄
在這里插入圖片描述
在這里插入圖片描述

2. 紅黑樹的插入:

(1)約定:

下面我們分析時的各節點命名:
下圖中假設我們把新增結點標識為c(cur),c的父親標識為p(parent),p的父親標識為g(grandfather),p的兄弟標識為u(uncle)

(2)紅黑樹插入的大致流程:
  1. 插入一個值按二叉搜索樹規則進行插入,插入后我們只需要觀察是否符合紅黑樹的4條規則。
  2. 如果是空樹插入,新增結點是黑色結點。如果是非空樹插入,新增結點必須為紅色結點,因為非空樹插入,新增黑色結點就破壞了規則4,規則4是很難維護的。
  3. 非空樹插入后,新增結點必須紅色結點,如果父親結點是黑色的,則沒有違反任何規則,插入結束。
  4. 非空樹插入后,新增結點必須紅色結點,如果父親結點是紅色的,則違反規則3。進一步分析,c是紅色,p為紅,g必為黑,這三個顏色都固定了,關鍵的變化看u的情況,需要根據u分為以下幾種情況分別處理。
(3)情況1:u存在且為紅(只變色)

c為紅,p為紅,g為黑,u存在且為紅,則將p和u變黑,g變紅。在把g當做新的c,繼續往上更新。
分析:因為pu都是紅色,g是黑色,把pu變黑,左邊子樹路徑各增加一個黑色結點,g再變紅,相當于保持g所在子樹的黑色結點的數量不變,同時解決了cp連續紅色結點的問題,需要繼續往上更新是因為,g是紅色,如果g的父親還是紅色,那么就還需要繼續處理;如果g的父親是黑色,則處理結束了;如果g就是整棵樹的根,再把g變回黑色。(因為根節點應該為黑色)
情況1只變色,不旋轉。所以無論cp的左還是右,pg的左還是右,都是上面的變色處理方式。

a. 具體示例:

在這里插入圖片描述

b. 抽象示例:

在這里插入圖片描述

情況1代碼實現:

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

(4)情況2:u 不存在或者存在且為黑(單旋+變色)
  1. c為紅,p為紅,g為黑,u不存在或者u存在且為黑
  2. u不存在,則c?定是新增結點,
  3. u存在且為黑,則c一定不是新增,c之前是黑色的,是在c的子樹中插入,符合情況1,變色將c從黑色變成紅色,更新上來的。
    分析:p必須變黑,才能解決連續紅黑結點的問題,u不存在或者是黑色的,這里單純的變色無法解決問題,需要旋轉+變色。

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

單旋+變色代碼實現:

在這里插入圖片描述

情況2:u 不存在或者 u 存在且為黑(雙旋+變色)
  1. c為紅,p為紅,g為黑,u不存在或者u存在且為黑。
  2. u不存在,則c一定是新增結點,
  3. u存在且為黑,則c一定不是新增,c之前是黑色的,是在c的子樹中插入,符合情況1,變色將c從黑色變成紅色,更新上來的。
    分析:p必須變黑,才能解決,連續紅色結點的問題,u不存在或者是黑色的,這里單純的變色無法解決問題,需要旋轉+變色。

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

雙旋+變色 代碼實現:

在這里插入圖片描述

當 p u 位置反過來時的代碼:

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

3. 紅黑樹的查找:

按二叉搜索樹的邏輯實現即可,搜索效率為O(logN)
在這里插入圖片描述
在這里插入圖片描述

4. 紅黑樹的驗證

這里獲取最長路徑和最短路徑,檢查最長路徑不超過最短路徑的2倍是不可行的,因為就算滿足這個條件,紅黑樹也可能顏色不滿足規則,當前暫時沒出問題,后續繼續插入還是會出問題的。所以我們還是去檢查4點規則,滿足這4點規則,一定能保證最長路徑不超過最短路徑的2倍。

  1. 規則1枚舉顏色類型,天然實現保證了顏色不是黑色就是紅色。
  2. 規則2直接檢查根即可。
  3. 規則3前序遍歷檢查,遇到紅色結點查孩子不太方便,因為孩子有兩個,且不一定存在,反過來檢查父親的顏色就方便多了。
  4. 規則4前序遍歷,遍歷過程中用形參記錄跟到當前結點的blackNum(黑色結點數量),前序遍歷遇到黑色結點就++blackNum,走到空就計算出了一條路徑的黑色結點數量。再任意一條路徑黑色結點數量作為參考值,依次比較即可。

在這里插入圖片描述在這里插入圖片描述
在這里插入圖片描述

5. 測試:

(1)插入及其合法性驗證:

在這里插入圖片描述

(2)性能測試:

在這里插入圖片描述
在這里插入圖片描述

完結!!!

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

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

相關文章

領域驅動設計(DDD)【23】之泛化:從概念到實踐

文章目錄 一 泛化基礎&#xff1a;理解DDD中的核心抽象機制1.1 什么是泛化&#xff1f;1.2 為什么泛化在DDD中重要&#xff1f;1.3 泛化與特化的雙向關系 二 DDD中泛化的實現形式2.0 實現形式概覽2.1 類繼承&#xff1a;最直接的泛化實現2.2 接口實現&#xff1a;更靈活的泛化方…

機箱流動空氣熱學仿真方案

機箱流動空氣熱學仿真方案(二維平面與三維) 一、物理模型與數學模型 1. 控制方程 流動與傳熱基本方程: 連續性方程:?(ρu) = 0動量方程(Navier-Stokes):ρ(u?)u = -?p + μ?u + F能量方程:ρc?(u?)T = k?T + Φ邊界條件: 入口:速度入口(u=u?, T=T?)出口:壓…

electron 如何配置 打開控制臺

在 Electron 應用中&#xff0c;打開開發者工具&#xff08;即控制臺&#xff09;通常有兩種方式&#xff1a; 程序運行時手動打開 在 Electron 應用中&#xff0c;你可以通過編程方式打開開發者工具。這通常在你需要調試時非常有用。你可以在你的主進程&#xff08;通常是 ma…

MR7350用TTL刷機救磚過程

很久之前就買了一臺Linksys的MR7350路由器&#xff0c;準備有OpenWRT的官方固件之后再拿它當輕NAS用&#xff0c;最近看到出了Snapshot版&#xff0c;于是就拿來刷機試試。經過我堅持不懈的折騰&#xff0c;終于把我的MR7350路由器刷成了磚&#xff0c;即便是通過開機過程中斷電…

在NPU單算子(torch_npu )執行時如何進行性能優化?以MinerU為例

1 MinerU介紹 在AI技術快速發展的今天&#xff0c;大量非結構化數據的處理成為亟待解決的問題。尤其是PDF文檔&#xff0c;作為最常見的文件格式之一&#xff0c;如何高效準確地提取其中的信息&#xff0c;成為了許多企業和研究機構的痛點。上海人工智能實驗室&#xff08;上海…

鴻蒙OS開發IoT控制應用:從入門到實踐

引言&#xff1a;萬物互聯時代的應用開發新范式 在物聯網(IoT)技術迅猛發展的今天&#xff0c;智能設備數量呈指數級增長。據IDC預測&#xff0c;到2025年全球IoT連接設備數將達到416億臺。面對碎片化的IoT設備和多樣化的控制需求&#xff0c;華為鴻蒙OS(HarmonyOS)應運而生&a…

五層網絡模型:網絡通信的核心框架

在網絡通信的世界里&#xff0c;五層網絡模型是一個基礎而關鍵的概念。它幫助我們理解數據是如何在網絡上從一個設備傳輸到另一個設備的。本文將詳細介紹五層網絡模型的每一層&#xff0c;以及它們在數據傳輸過程中的作用。 一、五層網絡模型概述 五層網絡模型是一種分層的網…

常見的強化學習算法分類及其特點

強化學習&#xff08;Reinforcement Learning, RL&#xff09;是一種機器學習方法&#xff0c;通過智能體&#xff08;Agent&#xff09;與環境&#xff08;Environment&#xff09;的交互來學習如何采取行動以最大化累積獎勵。以下是一些常見的強化學習算法分類及其特點&#…

【LeetCode 熱題 100】438. 找到字符串中所有字母異位詞——(解法三)不定長滑動窗口+數組

Problem: 438. 找到字符串中所有字母異位詞 題目&#xff1a;給定兩個字符串 s 和 p&#xff0c;找到 s 中所有 p 的 異位詞 的子串&#xff0c;返回這些子串的起始索引。不考慮答案輸出的順序。 【LeetCode 熱題 100】438. 找到字符串中所有字母異位詞——&#xff08;解法一&…

求區間最大值

題目描述 給定一個長度為 N 的數列&#xff0c;和 M 次詢問&#xff0c;求出每一次詢問的區間內數字的最大值。 輸入描述 第一行包含兩個整數 N,M&#xff0c;分別表示數列的長度和詢問的個數。 第二行包含 N 個整數&#xff08;記為&#x1d44e;&#x1d456;&#xff09;&am…

調試HDMI音頻能8通道播放聲音

一、使用場景 我們是通過rk主控的hdmi接口播放音視頻給到ite68051芯片解析出8聲道數據,分別通過4路i2s的數據腳給給到fpga去解析 調試步驟: 1.根據相關手冊配置hdmi輸出,hdmi聲卡注冊,如下: hdmi0_sound: hdmi0-sound {status = "disabled";compatible = &qu…

PowerBI 柱狀圖顯示MoM銷量環比示例,以及解決相同列值時設置柱子顏色的問題

先看效果: 假設有Sales表: 1. 我們先給它新增一個計算列&#xff0c;顯示銷售日期的年月 銷售日期YYYYMM YEAR(Sales[銷售日期])*100 MONTH(Sales[銷售日期]) 2. 然后新增一個計算表&#xff0c;用于保存當前最大的銷售日期&#xff0c;和上一個月的日期 DateComparisonT…

【docker】構建時使用宿主機的代理

docker構建過程中報錯: pip 下載失敗 解決辦法:傳遞宿主機的代理 把宿主機的 HTTP_PROXY/HTTPS_PROXY 傳進去,導致容器內的 pip 依然連不上代理,下載 build-dependencies(比如 setuptools)就會失敗。 下面兩步即可解決: Docker 構建階段,127.0.0.1:7890 指向的是 容…

[Java 基礎]算法

什么是算法 程序 數據結構 算法 算法&#xff08;Algorithm&#xff09;就是解決問題的步驟&#xff0c;就像做菜的食譜一樣&#xff0c;告訴計算機一步一步如何完成任務。 例如&#xff1a; 排序算法&#xff1a;把一堆數字從小到大排列搜索算法&#xff1a;在一堆數據里…

C++理解for循環 計算題三

計算a的值 #include <iostream> using namespace std; int main() { int a0;for(int i0;i<3;i){for(int j0;j<3;j){aij;}}cout<<"a的值是 "<<a<<endl; return 0; } 計算a的值 #include <iostream> using namespace std; int …

梳理React中的fiber架構

文章目錄 產生背景核心概念工作原理工作流程優勢特點 產生背景 在React16之前使用的虛擬DOM是數組的形式&#xff0c;又因為React本身是應用級框架&#xff0c;狀態改變后并不能準確知道是哪個組件發生了改變&#xff0c;只能對整個應用進行diff協調&#xff0c;受限于虛擬DOM…

Modbus 數據模型:線圈、寄存器與功能碼詳解(二)

三、Modbus 功能碼詳解 3.1 功能碼分類與作用 Modbus 功能碼是 Modbus 通信協議中的關鍵組成部分&#xff0c;它如同一個 “指令指揮官”&#xff0c;在通信事務處理中扮演著核心角色。功能碼占用 1 個字節的空間&#xff0c;取值范圍為 1 到 255 &#xff08;0x01 - 0xFF&am…

多表連接查詢:語法、注意事項與最佳實踐

&#x1f517; 多表連接查詢&#xff1a;語法、注意事項與最佳實踐 多表連接是 SQL 的核心能力&#xff0c;用于關聯多個表的數據。以下是深度解析&#xff0c;涵蓋語法規范、性能陷阱及實戰技巧&#xff1a; &#x1f4dc; 一、多表連接語法大全 1. 顯式連接&#xff08;推薦…

使用Calibre對GDS進行數據遍歷

在芯片的GDS數據里&#xff0c;使用Calibre對數據進行處理是非常常見的操作&#xff0c;但是GDS是一種和常規設計結構不太一樣的一種數據&#xff0c;這里&#xff0c;通過這個小小的科普文章&#xff0c;一起看看怎么樣在GDS里邊做數據漫游吧&#xff01;閑言少敘&#xff0c;…

PyQtNode Editor 第二篇自定義可視化視圖

在第一篇博客中,我們已經完成了 PyQtNode Editor 的基礎環境搭建,并深入解析了自定義圖形場景QDMGraphicsScene的實現原理。那個帶有網格背景的場景就像一張空白的圖紙,現在我們要在這張圖紙上開始繪制真正的節點系統。 今天我們將聚焦于節點編輯器的核心數據結構設計,實現…