數據結構:紅黑樹(Red-Black Tree)

目錄

從AVL樹的“煩惱”說起

如何用“顏色”來定義“大致平衡”?—— 紅黑樹的五個規則

五個規則如何保證“大致平衡”?

用 C/C++ 代碼定義紅黑樹的結構

定義顏色和節點結構

?定義樹的結構和哨兵節點


從AVL樹的“煩惱”說起

我們從已經了解的 AVL 樹出發。AVL 樹的出發點是什么?

是為了解決二叉搜索樹(Binary Search Tree, BST)在最壞情況下退化成鏈表的問題。它的核心思想是:強制平衡。它有一個非常嚴格的規定:“任意節點左右子樹的高度差 ≤ 1”。

這個規定很有效,保證了樹的高度始終在 O(logN) 級別,因此查找效率非常高。但它的“煩惱”也來源于此:

📌 為了維持這個嚴格的平衡,AVL 樹的插入和刪除操作可能會導致頻繁的旋轉 (Rotation)。有時候,僅僅插入一個節點,就可能需要從插入點一直回溯到根節點,進行多次旋轉。旋轉操作本身是有開銷的。

既然“絕對平衡”的維護成本有點高,我們能不能稍微“放松”一點要求?我們不追求“完美身高”,只追求“身材勻稱”,只要最長路徑和最短路徑的長度別差得太離譜,那它的查找效率不也能保證在 O(logN) 嗎????

這個“放松要求,換取插入/刪除時更少操作”的想法,就是紅黑樹誕生的根本動機。

第一性原理推導:

  1. 目標: 保持樹的查找效率,即樹的高度維持在 O(logN)。

  2. 現有方案: AVL 樹通過嚴格限制左右子樹高度差來實現。

  3. 痛點: 維護嚴格平衡的成本(旋轉次數)較高。

  4. 新思路: 尋找一種弱一點的平衡標準。這個標準必須足夠強,以保證樹高為 O(logN);又必須足夠弱,以減少插入/刪除時維護平衡的代價。

紅黑樹就是這個新思路的杰出實現。它放棄了用“高度”這個屬性來做限制,而是引入了一個全新的、更巧妙的屬性:顏色 (Color)


如何用“顏色”來定義“大致平衡”?—— 紅黑樹的五個規則

好,我們現在給每個節點增加一個屬性:color,它可以是紅色 (RED)或黑色 (BLACK)。通過一些“顏色規則 (Coloring Rules)”來限制樹的形態,保證從根到任意葉子的路徑長度不會差太多。

1. 二叉搜索樹的復雜度依賴高度

  • 查找(Search)復雜度 = O(h),其中 h 是樹高。

  • 如果 h 太大(比如退化成鏈表),復雜度退化為 O(N)

  • 所以我們必須保證 h = O(log N)

2. 最短路徑長度與節點數的關系

  • 在一棵二叉樹里,最短路徑長度(記為 h_min)指從根到某個葉子所經過的邊數。

  • 如果所有路徑至少有 h_min 個節點(或邊),那么這棵樹至少包含:2^(h_min) - 1?個節點(這是滿二叉樹的下界)。

  • 因此:N ≥ 2^(h_min) - 1? ? h_min ≤ log2(N+1)

3. 如果最長路徑 ≤ 2 × 最短路徑

設:

  • h_min = 最短路徑高度

  • h_max = 最長路徑高度 = 樹的高度

如果能保證:h_max ≤ 2 * h_min

那么結合上面的不等式:h_min ≤ log2(N+1)? ?? ?h_max ≤ 2 * log2(N+1)

于是我們得到了:h_max = O(log N)

我們的最終目標是證明:

一棵紅黑樹從根到最遠葉子節點的路徑長度,不會超過到最近葉子節點路徑長度的兩倍。

如果能證明這一點,就說明樹的高度依然是 O(logN),我們的目標就達成了。

我們來一步步推導出這些規則:

1??:每個節點要么是紅色,要么是黑色。

這是最基本定義,就像說“游戲里的棋子要么是黑的,要么是白的”。沒有它,后續規則無從談起。

2??:根節點是黑色。

這條規則不是強制性的,但它能簡化很多問題。可以把它看作一個“基準”或“錨點”。

如果根節點是紅色,它可能會違反其他規則(比如后面會提到的“紅色節點的子節點不能是紅色”),所以干脆定為黑色,讓處理更統一。

3??:所有葉子節點都是黑色。

這里的“葉子節點”比較特殊,它不是指最后一個有數據的節點,而是指其下方的 NULL 指針。

在紅黑樹的實現中,我們通常會用一個統一的、黑色的哨兵節點 (Sentinel Node) 來代表所有的 NULL

這樣做的好處是,處理邊界情況(比如一個節點只有一個子節點)時,我們不需要寫大量的 if (node->left != NULL) 判斷,因為它的 leftright 總是指向一個有效的(哨兵)節點。這純粹是為了簡化代碼實現。

至此,我們有了基本的顏色框架。但這些還不足以保證平衡。現在,我們需要引入真正限制樹“形狀”的規則。

4??:紅色節點的子節點必須是黑色的。 (也就是說,不能有兩個連續的紅色節點)

這是實現“放松平衡”的核心規則之一。如果允許紅色節點串在一起(紅->紅->紅...),那這條路徑就會被無限制地拉長,樹就會失衡。

這條規則強制打斷了“紅色路徑”,確保了從根到葉子的路徑上,紅色節點不會連續出現。

5??:從任一節點到其每個葉子(NIL 哨兵節點)的所有路徑,都包含相同數目的黑色節點。

這是另一條核心規則,也是最難理解但最關鍵的一條。它定義了一個叫做“黑高 (Black-Height)”的概念。

這條規則強制要求,無論你從一個節點 x 出發,走左邊還是走右邊,到達終點(葉子)時,路上經過的黑色節點數量必須完全一樣。這就像給樹建立了一個“黑色的骨架”,這個骨架是完美平衡的。紅色節點則可以看作是“填充”在這個黑色骨架之間的節點。


五個規則如何保證“大致平衡”?

現在我們來驗證一下,這五條規則是否達成了我們的最終目標:最長路徑 <= 2 * 最短路徑

📍最短路徑:

考慮從根節點到一個葉子節點的最短路徑。這條路徑上會包含最少的節點。要讓節點數最少,我們就應該盡量少放紅色節點。

根據規則4,紅色節點不能連續,所以最短的路徑就是一條純黑色的路徑。這條路徑的長度就是這棵樹的黑高 (Black-Height),我們記為 bh

📌最長路徑:

要讓路徑最長,我們就應該塞進盡可能多的紅色節點。根據規則4,每兩個黑色節點之間最多只能插入一個紅色節點(黑 -> 紅 -> 黑 -> 紅 ...)。

由于規則5保證了任何路徑上的黑色節點數量都是 bh,那么在最長路徑上,我們最多也就能塞進 bh 個紅色節點。

所以:

  • 最短路徑長度 = bh (全是黑色節點)

  • 最長路徑長度 <= bh (黑色節點) + bh (紅色節點) = 2 * bh

結論最長路徑長度 <= 2 * 最短路徑長度

這個結論證明了紅黑樹的高度始終保持在 O(logN) 級別。我們成功地用五條看似無關的顏色規則,間接實現了樹的平衡,而且這個平衡比 AVL 樹更“寬松”。這種寬松,將為我們后續的插入和刪除操作帶來更低的維護成本。


用 C/C++ 代碼定義紅黑樹的結構

好了,理論推導結束。我們現在開始寫代碼,一步步定義出紅黑樹的節點和樹的結構。

定義顏色和節點結構

首先,我們需要一個 enum 來表示顏色。然后定義節點結構 RBTNode

除了BST原有的 keyleftright 指針,我們還需要 color 屬性和一個指向父節點 (parent) 的指針。父節點指針在后續的旋轉和調整中非常有用,可以避免復雜的遞歸或棧來尋找父節點。

// 使用 C 風格的代碼,不涉及高級語法和STL#include <stdio.h>// 專有名稱: 顏色 (Color)
typedef enum {RED,    // 紅色BLACK   // 黑色
} Color;// 專有名稱: 紅黑樹節點 (Red-Black Tree Node)
typedef struct RBTNode {int key;              // 鍵值Color color;          // 顏色struct RBTNode *left;   // 左子節點指針struct RBTNode *right;  // 右子節點指針struct RBTNode *parent; // 父節點指針
} RBTNode;

這段代碼非常基礎,就是定義了我們討論中需要的所有元素:鍵值、顏色、以及三個方向的指針

?定義樹的結構和哨兵節點

根據規則3,我們需要一個黑色的哨兵節點來代表所有的 NULL 葉子。我們可以定義一個全局的哨兵節點 NIL。樹本身可以用一個指向根節點的指針來表示。

// 接著上面的代碼// 哨兵節點 (Sentinel Node),代表所有的NULL葉子
RBTNode* NIL;// 紅黑樹結構,本質上是一個指向根節點的指針
typedef struct RedBlackTree {RBTNode* root;
} RedBlackTree;// 初始化函數,用于創建NIL節點
void initializeNIL() {NIL = new RBTNode; // 在C++中用new,在C中用mallocNIL->color = BLACK;NIL->key = 0; // key值無所謂NIL->left = NULL;NIL->right = NULL;NIL->parent = NULL;
}

為什么需要 NIL 哨兵節點?

想象一下,如果沒有 NIL,當你想訪問 node->left->color 時,你必須先檢查 node->left是不是 NULL。而有了 NIL,任何一個節點的 leftright 指針,要么指向一個有效的數據節點,要么指向 NIL

因為 NIL 是一個有確定顏色(黑色)的真實節點,所以你可以安全地訪問 node->left->color,這會讓代碼變得非常整潔。

一個新創建的樹,其根節點應該指向 NIL

// 創建一棵空樹
RedBlackTree* createRedBlackTree() {RedBlackTree* tree = new RedBlackTree; // C: mallocif (NIL == NULL) {initializeNIL(); // 確保NIL只被初始化一次}tree->root = NIL; // 空樹的根指向NILreturn tree;
}

到目前為止,我們已經成功地:

  1. 從第一性原理推導出了紅黑樹存在的必要性。

  2. 推導出了定義紅黑樹的5個核心規則。

  3. 證明了這5個規則如何保證樹的“大致平衡”。

  4. 用基礎的 C/C++ 代碼定義了紅黑樹的節點、樹結構以及核心的 NIL 哨兵節點。

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

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

相關文章

Ubuntu22.04安裝VMware Tools

文章目錄前言安裝open-mv-tools前言 本教程使用的版本是Ubuntu22.04.5&#xff0c;由于虛擬機上面的重新安裝VMware Tools是灰的&#xff0c;于是自動下載安裝open-mv-tools&#xff0c; 安裝open-mv-tools 打開終端&#xff0c;更新一下 sudo apt update這一步可能需要先…

DBeaver連接SQL Server時添加驅動后仍提示找不到驅動的解決方法

DBeaver連接SQL Server時添加驅動后仍提示找不到驅動的解決方法 在使用DBeaver連接SQL Server時&#xff0c;即使您已手動添加驅動文件&#xff0c;系統仍提示“找不到驅動”&#xff0c;這通常是由驅動配置錯誤、版本不兼容或SQL Server設置問題引起的。以下我將逐步為您提供解…

JVM之【類加載系統】

目錄 前言 類加載過程 類加載 執行過程 加載階段 連接階段 初始化階段 類加載器 BootstrapClassLoader ExtClassLoader AppClassLoader 類加載器之間的關系 雙親委派機制 核心思想 好處 源碼分析 類加載器之間的父子層級關系 雙親委派的體現 前言 上文中提到…

【 限流技術 | 從四大限流算法到Redisson令牌桶實踐 】

引言&#xff1a;為什么需要限流&#xff1f;在現代分布式系統中&#xff0c;服務的穩定性是至關重要的。在遇到突發的請求量激增&#xff0c;惡意的用戶訪問&#xff0c;亦或是請求頻率過高給下游服務帶來較大壓力時&#xff0c;我們常常需要通過緩存、限流、熔斷降級、負載均…

深入解析Java NIO多路復用原理與性能優化實踐指南

深入解析Java NIO多路復用原理與性能優化實踐指南 技術背景與應用場景 在高并發網絡編程中&#xff0c;傳統的阻塞 I/O 模型往往因每個連接都占用一個線程或一個系統調用而導致線程資源浪費、線程切換開銷劇增等問題&#xff0c;難以滿足數萬甚至數十萬并發連接的負載要求。Jav…

目標檢測數據集 第006期-基于yolo標注格式的汽車事故檢測數據集(含免費分享)

目錄 目標檢測數據集 第006期-基于yolo標注格式的汽車事故檢測數據集(含免費分享) 超實用汽車事故檢測數據集分享&#xff0c;助力計算機視覺研究&#xff01; 1、背景 2、數據詳情 數據集基本信息 結構組成 標注格式與示例 類標簽說明 數據增強情況 3、應用場景 4、…

應用密碼學(書籍學習筆記、基礎知識) 一

本博客為讀《應用密碼學》所得筆記 文章目錄一、 加密與解密1.2 秘鑰Key1.2.1 引入秘鑰K1.2.2 加密秘鑰K1&#xff0c;解密秘鑰K2二、對稱算法 VS 公開密鑰算法**① 對稱算法** - 傳統密碼算法 **(Symmetric Algorithm) &#x1f511;****② 非對稱算法特點** - 公開秘鑰算法 *…

【攻防世界】Web_php_include

1.信息收集題目&#xff1a;Web_php_include &#xff1a;PHP文件包含漏洞2.思路&#xff1a;1.代碼審計&#xff1a;<?php show_source(__FILE__); echo $_GET[hello]; $page$_GET[page]; while (strstr($page, "php://")) { //在一個字符串中查…

cmake--CPack/deb

deb包的需求 怎么使用cmake把項目的依賴想打包為deb包,把項目的可執行文件和依賴文件打包為deb包,又怎么樣配置apt源,讓項目在jenkins構建之后,可以通過sudo apt install 下載deb包和安裝到任意主機上? 整體流程概覽 使用CMake構建項目:確保你的項目可以被CMake正確編譯…

七十五、【Linux數據庫】部署Redis服務 、 部署LNMP+Redis

Redis 與 LNMP 集成功能概述 Redis 核心功能 內存數據存儲:高速讀寫性能 數據結構豐富:字符串、哈希、列表、集合等 持久化支持:RDB快照和AOF日志 發布訂閱:消息隊列功能 高可用:主從復制、哨兵模式、集群 LNMP+Redis 集成價值 會話共享:多Web服務器共享Session 數據緩存…

從YOLOv5到RKNN:零沖突轉換YOLOv5模型至RK3588 NPU全指南

從YOLOv5到RKNN&#xff1a;零沖突轉換YOLOv5模型至RK3588 NPU全指南 在嵌入式AI領域&#xff0c;將訓練好的深度學習模型高效部署到邊緣設備的NPU&#xff08;神經網絡處理器&#xff09;上是提升性能的關鍵。本文將詳細介紹如何在Ubuntu 20.04環境下&#xff0c;將YOLOv5l模型…

DNS的解析過程是怎樣的?它基于傳輸層的什么協議?

問題DNS的解析過程是怎樣的&#xff1f;它基于傳輸層的什么協議&#xff1f;我的回答&#xff1a;DNS解析過程是將域名轉換為IP地址的一系列步驟。這個過程涉及多級緩存和查詢&#xff1a;首先是瀏覽器緩存&#xff0c;瀏覽器會先檢查自己的DNS緩存是否有記錄。接著是操作系統緩…

模擬互聯網大廠Java面試:電商場景下的技術探討

模擬互聯網大廠Java面試&#xff1a;電商場景下的技術探討 場景概述 在這場模擬面試中&#xff0c;我們設定了一位互聯網大廠的面試官與候選人小C之間的對話。面試官嚴肅專業&#xff0c;而小C則是搞笑的“水貨程序員”。通過三輪問答&#xff0c;我們探索了Java技術棧在電商場…

遙感機器學習入門實戰教程|Sklearn案例⑤:集成學習方法全覽

在機器學習的實際應用中&#xff0c;單一分類器往往存在局限&#xff1a;比如決策樹容易過擬合&#xff0c;kNN 對噪聲敏感&#xff0c;邏輯回歸在高維數據下收斂慢。為了提升整體效果&#xff0c;我們通常會采用 集成學習&#xff08;Ensemble Learning&#xff09;。 這篇文章…

大模型在垂直場景中的創新應用:搜索、推薦、營銷與客服的新玩法

1. 引言 背景介紹:簡述大模型(如GPT、BERT等)的發展歷程及其在AI領域的核心作用,強調其在垂直場景中的潛力。 主題聚焦:說明本文將深入探討搜索、推薦、營銷、客服四大場景,分析大模型帶來的創新開發方式。 目的與意義:闡述新玩法如何提升效率、增強用戶體驗,并推動行業…

華為倉頡語言的class(類)初步

華為倉頡語言的class&#xff08;類&#xff09;初步 class 概念 【官方文檔 https://cangjie-lang.cn/docs?url%2F1.0.0%2Fuser_manual%2Fsource_zh_cn%2Fclass_and_interface%2Fclass.html 】 class 是倉頡面向對象體系的核心&#xff0c;用來描述“引用類型”對象。與 s…

健康常識查詢系統|基于java和小程序的健康常識查詢系統設計與實現(源碼+數據庫+文檔)

健康常識查詢系統 目錄 基于java和小程序的健康常識查詢系統設計與實現 一、前言 二、系統設計 三、系統功能設計 小程序功能設計 后臺功能設計 四、數據庫設計 五、核心代碼 六、論文參考 七、最新計算機畢設選題推薦 八、源碼獲取&#xff1a; 博主介紹&#xf…

MySQL的高可用+MHA

即MySQL 主從復制高可用架構&#xff0c;是一套優秀的MySQL 高可用解決方案&#xff0c;由日本 DeNA 公司 youshimaton 開發&#xff0c;主要用于保障 MySQL 數據庫在主服務器出現故障時&#xff0c;能快速進行主從切換&#xff0c;減少數據庫服務中斷時間。其核心特點包括&…

淘寶pc端首頁做了哪些性能優化?

淘寶PC端首頁作為中國電商領域流量最大的頁面之一&#xff0c;其性能優化手段可以說是業界標桿&#xff0c;非常全面和深入。這些優化不是單一技術&#xff0c;而是一個完整的體系。 我們可以從以下幾個層面來分析和理解淘寶首頁所做的性能優化&#xff1a; 一、核心指標與整體…

讓醫學數據更直觀——MedCalc 23.1.7 最新版使用體驗

軟件介紹 MedCalc 23.1.7是一款功能強大的生物醫學研究統計軟件&#xff0c;專為醫學科研人員和醫療保健專家設計。它提供了豐富的統計分析工具和方法&#xff0c;旨在幫助用戶更好地分析和解釋醫學數據。以下是該軟件的一些主要特點&#xff1a; 一、數據導入和管理 支持導…