紅黑樹的平衡

1.紅黑樹的概念

紅黑樹,是一種二叉搜索樹,但在每個結點上增加一個存儲位表示結點的顏色,可以是Red或
Black。 通過對任何一條從根到葉子的路徑上各個結點著色方式的限制,紅黑樹確保沒有一條路
徑會比其他路徑長出倆倍
,因而是接近平衡的。

?

2.紅黑樹的性質?

1. 每個結點不是紅色就是黑色
2. 根節點是黑色的?
3. 如果一個節點是紅色的,則它的兩個孩子結點是黑色的 (沒有連續的紅色節點)
4. 對于每個結點,從該結點到其所有后代葉結點的簡單路徑上,均 包含相同數目黑色結點?
5. 每個葉子結點都是黑色的(此處的葉子結點指的是空結點)NIF節點
思考:為什么滿足上面的性質,紅黑樹就能保證:其最長路徑中節點個數不會超過最短路徑節點
個數的兩倍?看圖

路徑:從該節點到NIF節點

最短路徑:全黑節點

最長路徑:一黑一紅

?3.紅黑樹的平衡

節點定義

enum Color
{RED,BLACK,
};template<class K,class V>
class RBNode
{
public:typedef RBNode<K, V> Node;RBNode(const pair<K, V>& kv):_left(nullptr), _right(nullptr), _parent(nullptr), _col(RED), _kv(kv){}Node* _left;Node* _right;Node* _parent;Color _col;pair<K, V> _kv;//庫里面提供的結構體,表示key和value};

顏色初始化必須是紅色,如果插入的是黑色,必定會影響每條路徑的黑色節點的數量,紅色的話只會影響該條路徑

插入


template<class K,class V>
class RBTree
{
public:typedef RBNode<K, V> Node;bool Insert(const pair<K, V>& kv){if (_root == nullptr){_root = new Node(kv);_root->_col = BLACK;return true;}Node* cur = _root;Node* parent = nullptr;while (cur){if (kv.first < cur->_kv.first){parent = cur;cur = cur->_left;}else if (kv.first > cur->_kv.first){parent = cur;cur = cur->_right;}else{return false;}}cur = new Node(kv);if (parent->_kv.first > kv.first){parent->_left = cur;}else{parent->_right = cur;}cur->_parent = parent;//...........}private:Node* _root = nullptr;
};

插入分為三種情況(p為parent,g為grandparent,u為uncle)

cur一定為紅色了

1:p是黑色,不用處理

2:p是紅色,u存在且為紅色

3:p是紅色,u不存在或存在為黑色

情況2:?

p是紅色,u存在且為紅色

變色+向上

?

情況3:

?p是紅色,u不存在或存在為黑色

u在右孩子時

u在左孩子同理?

下面是插入后面實現的代碼,里面有注釋

            while(parent&&parent->_col == RED){Node* grandparent = parent->_parent;if (grandparent->_right == parent){Node* uncle = grandparent->_left;//情況1:u存在且為紅,變色加向上調整if (uncle && uncle->_col == RED){parent->_col = BLACK;uncle->_col = BLACK;grandparent->_col = RED;//向上調整cur = grandparent;parent = cur->_parent;}else//情況2a:u不存在或者u存在且為黑  旋轉+變色{/*    gu     pc*///左單旋+變色if (parent->_right == cur){RotateL(grandparent);grandparent->_col = RED;parent->_col = BLACK;}else{/*    gu     pc    *///右單旋+左單旋+變色RotateR(parent);RotateL(grandparent);cur->_col = BLACK;grandparent->_col = RED;}break;}}else{Node* uncle = grandparent->_right;//情況1:u存在且為紅,變色加向上調整if (uncle && uncle->_col == RED){parent->_col = BLACK;uncle->_col = BLACK;grandparent->_col = RED;//向上調整cur = grandparent;parent = cur->_parent;}else//情況2b:u不存在或者u存在且為黑  旋轉+變色{/*    gp     u c              *///右單旋+變色if (parent->_right == cur){RotateR(grandparent);grandparent->_col = RED;parent->_col = BLACK;}else{/*    gp     uc        *///左單旋+右單旋+變色RotateL(parent);RotateR(grandparent);cur->_col = BLACK;grandparent->_col = RED;}break;}}}_root->_col = BLACK;//管你變成什么色,根反正最后還是黑色return true;

?4.紅黑樹的驗證

驗證是紅黑樹,就要滿足他的性質,首先不能出現連續紅色節點,其次每條路徑的黑色節點的數量要相等

不能出現連續紅色節點:不要用cur,然后和cur->孩子來比較,因為會有兩個孩子,比較麻煩,可以用cur->parent來比較

每條路徑的黑色節點的數量要相等:先算出一條路徑的黑色節點的數量,作為基準值,進行比較

bool IsRBTree(){if (_root && _root->_col == RED){cout << "根節點顏色是紅色" << endl;return false;}int nummark = 0;//給個黑色節點基準值,然后和它比較Node* cur = _root;while (cur){if(cur->_col == BLACK)nummark++;cur=cur->_left;}return _Check(_root, 0, nummark);}
bool _Check(Node* root, int blacknum, int nummark){if (root == nullptr){if (nummark != blacknum){cout << "某條路徑黑色節點的數量不相等" << endl;cout << blacknum << endl;return false;}return true;}if (root->_col == BLACK){blacknum++;}if (root->_col == RED && root->_parent && root->_parent->_col == RED){cout << "具有連續的紅色節點" << endl;return false;}return _Check(root->_left, blacknum, nummark)&& _Check(root->_right, blacknum, nummark);}
void testRBTree()
{srand(time(0));const size_t N = 5000000;RBTree<int, int> t;for (size_t i = 0; i < N; ++i){size_t x = rand() + i;t.Insert(make_pair(x, x));}//t.Inorder();cout << t.IsRBTree() << endl;
}

?

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

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

相關文章

什么是apt

2024年5月15日&#xff0c;周三上午 apt 是 “Advanced Packaging Tool” 的縮寫&#xff0c;它是 Debian 及其衍生版&#xff08;如 Ubuntu&#xff09;中用于管理軟件包的命令行工具。apt 提供了一個統一的接口來安裝、更新、升級、刪除和搜索軟件包。 以下是 apt 的一些主要…

合合信息:TextIn文檔解析技術與高精度文本向量化模型再加速

文章目錄 前言現有大模型文檔解析問題表格無法解析無法按照閱讀順序解析文檔編碼錯誤 訴求文檔解析技術技術難點技術架構關鍵技術回根溯源 文本向量化模型結語 前言 隨著人工智能技術的持續演進&#xff0c;大語言模型在我們日常生活中正逐漸占據舉足輕重的地位。大模型語言通…

Java基礎(36)應用服務器優化技術有哪些

應用服務器優化是一個復雜的過程&#xff0c;涉及到服務器硬件資源、操作系統、網絡、應用程序代碼、數據庫等多個層面。下面是一些深入詳細的應用服務器優化技術&#xff1a; 系統級優化 硬件優化 提升CPU性能&#xff1a;使用更多核心的CPU或者升級到更高頻率的CPU。增加內…

Scala基礎

目錄 1.安裝與運行Scala 任務描述 了解Scala語言 了解Scala特性 安裝Scala 運行Scala 2.定義函數識別號碼類型 了解數據類型 定義與使用常量、變量 使用運算符 定義與使用數組 任務實現 3.基本語法 1 變量 2 字符串 3 數據類型&操作符 4 條件表達式 5 循環…

idea使用gitee基本操作流程

1.首先&#xff0c;每次要寫代碼前&#xff0c;先切換到自己負責的分支 點擊簽出。 然后拉取一次遠程master分支&#xff0c;保證得到的是最新的代碼。 寫完代碼后&#xff0c;在左側欄有提交按鈕。 點擊后&#xff0c;選擇更新的文件&#xff0c;輸入描述內容&#xff08;必填…

五分鐘“手撕”時間復雜度與空間復雜度

目錄 一、算法效率 什么是算法 如何衡量一個算法的好壞 算法效率 二、時間復雜度 時間復雜度的概念 大O的漸進表示法 推導大O階方法 常見時間復雜度計算舉例 三、空間復雜度 常見時間復雜度計算舉例 一、算法效率 什么是算法 算法(Algorithm)&#xff1a;就是定…

C++|多態性與虛函數(2)|虛析構函數|重載函數|純虛函數|抽象類

前言 看這篇之前&#xff0c;可以先看多態性與虛函數&#xff08;1&#xff09;?? C|多態性與虛函數&#xff08;1&#xff09;功能綁定|向上轉換類型|虛函數-CSDN博客https://blog.csdn.net/weixin_74197067/article/details/138861418?spm1001.2014.3001.5501這篇文章會…

【Java開發面試系列】JVM相關面試題(精選)

【Java開發面試系列】JVM相關面試題&#xff08;精選&#xff09; 文章目錄 【Java開發面試系列】JVM相關面試題&#xff08;精選&#xff09;前言一、JVM組成二、類加載器三、垃圾回收四、JVM實踐&#xff08;調優&#xff09; &#x1f308;你好呀&#xff01;我是 山頂風景獨…

【十大排序算法】----C語言版插入排序(詳細圖解)

目錄 一&#xff1a;插入排序——原理 二&#xff1a;插入排序——分析 三&#xff1a;插入排序——實現 四&#xff1a;插入排序——效率 一&#xff1a;插入排序——原理 插入排序的原理和基本思想&#xff1a;把待排序的記錄按其關鍵碼值的大小逐個插入到一個已經排好序…

無需重啟 NGINX 開源版即可實現 SSL/TLS 證書輪換

原文作者&#xff1a;Maxim Ivanitskiy of F5 原文鏈接&#xff1a;無需重啟 NGINX 開源版即可實現 SSL/TLS 證書輪換 轉載來源&#xff1a;NGINX 開源社區 NGINX 唯一中文官方社區 &#xff0c;盡在 nginx.org.cn 在高性能 Web 服務器領域&#xff0c;NGINX 是一個廣受歡迎的…

Django使用

一、根目錄下安裝 pip install django 二、創建djiango項目 django-admin startproject 項目名稱 三、創建app python manage.py startapp app名稱 四、啟動 python manage.py runserver 五、編寫URL與視圖關系&#xff0c;相對路徑 1、manage.py&#xff08;見資源綁定…

mysql 8 創建用戶并賦予改用戶指定數據庫權限

一、使用客戶端工具登錄mysql 二、創建用戶 -- 低版本數據庫 create user 用戶名% identified by 密碼; -- 高版本數據庫 create user 用戶名% identified with mysql_native_password by 密碼; -- 示例1&#xff1a; create user test% identified with mysql_native_passwor…

apt和apt-get有什么區別

2024年5月15日&#xff0c;周三上午 apt 和 apt-get 都是 Debian 及其衍生版&#xff08;如 Ubuntu&#xff09;中用于軟件包管理的工具&#xff0c;但它們之間存在一些差異。 功能和目的&#xff1a; apt 是 apt-get 的改進版本&#xff0c;提供了更簡潔和更直觀的命令選項。…

多元化、高辨識顯示丨基于G32A1445的汽車尾燈解決方案

由剎車燈、倒車燈、轉向燈、霧燈等組成的汽車尾燈&#xff0c;既能在光線低暗時發出照明信息&#xff0c;也可向周圍環境傳遞車輛的行駛狀態與意圖信號&#xff0c;對于行車安全起著至關重要的作用。與傳統尾燈相比&#xff0c;貫穿式汽車尾燈更加醒目、美觀、安全&#xff0c;…

CSS2(一):CSS選擇器

文章目錄 1、CSS基礎1.1 CSS簡介1.2 CSS編寫位置1.2.1 行內樣式1.2.2 內部樣式1.2.3 外部樣式1.2.4 樣式優先級 1.2.5 CSS代碼風格 2、CSS選擇器2.1、基本選擇器2.1.1 通配選擇器2.1.2 元素選擇器2.1.3 類選擇器2.1.4 ID選擇器2.1.5 總結 2.2、CSS復合選擇器2.2.1 交集選擇器2.…

海外媒體宣發:新加坡.馬來西亞如何在海外媒體投放新聞通稿-大舍傳媒

導言 隨著全球化的進程加速&#xff0c;海外市場對于企業的發展越來越重要。而在海外媒體上宣傳企業的新聞通稿&#xff0c;成為了拓展海外市場和提升企業知名度的重要手段之一。本文將介紹大舍傳媒對于如何在海外媒體上投放新聞通稿的經驗和策略。 準備工作&#xff1a;了解…

Hive 特殊的數據類型 Array、Map、Struct

Array 數組類型&#xff0c;存儲數據類型一致的列表數據。 我們可以使用 array 方法來創建一個數組&#xff0c;如下所示&#xff1a; select array(1,2,3,4,5);如果其中的數據類型不一致&#xff0c;那么它會轉換成統一的數據類型&#xff08;前提是能夠進行轉換&#xff0…

力扣HOT100 - 322. 零錢兌換

解題思路&#xff1a; 動態規劃 class Solution {public int coinChange(int[] coins, int amount) {int[] dp new int[amount 1];Arrays.fill(dp, amount 1);dp[0] 0;for (int i 1; i < amount; i) {for (int j 0; j < coins.length; j) {if (coins[j] < i) …

word內容wxml轉化html標簽對照表

1. 標簽 w:document document 文檔w:bodybody文檔的主體w:sectPrsection——w:pp/div段落w:rspan行內元素w:ttext文本w:tbltable表格w:trtr表格行w:tctd單元格w:brbr換行w:hyperlinka超鏈接w:roundrectdiv/canvas塊w:pictimg圖片w:inlinespan行元素w:oMathmath公式w:subsub下標…

寵物管理系統帶萬字文檔

文章目錄 寵物管理系統一、項目演示二、項目介紹三、19000字論文參考四、部分功能截圖五、部分代碼展示六、底部獲取項目源碼和萬字論文參考&#xff08;9.9&#xffe5;帶走&#xff09; 寵物管理系統 一、項目演示 寵物管理系統 二、項目介紹 基于springbootvue的前后端分離…