RBTree的模擬實現

1:紅黑樹的概念

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

1:紅黑樹的規則

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

2:紅黑樹確保最短路徑的方法

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

3: 紅?樹的效率

假設N是紅?樹樹中結點數量,h最短路徑的?度,那么, 由此推出,也就是意味著紅?樹增刪查改最壞也就是?最?路徑 ,那么時間復雜度還是。2h ? 1 <= N < 22?h ? 1h ≈ logN 2 ? logNO(logN)紅?樹的表達相對AVL樹要抽象?些,AVL樹通過?度差直觀的控制了平衡。紅?樹通過4條規則的顏?約束,間接的實現了近似平衡,他們效率都是同?檔次,但是相對??,插?相同數量的結點,紅?樹的旋轉次數是更少的,因為他對平衡的控制沒那么嚴格。

2:紅黑樹的模擬實現

1:紅黑樹的結構

// 枚舉值表示顏色
enum Colour
{RED,BLACK
};
// 這里我們默認按key/value結構實現
template<class K, class V>
struct RBTreeNode
{// 這里更新控制平衡也要加入parent指針pair<K, V> _kv;RBTreeNode<K, V>* _left;RBTreeNode<K, V>* _right;RBTreeNode<K, V>* _parent;Colour _col;RBTreeNode(const pair<K, V>& kv):_kv(kv), _left(nullptr), _right(nullptr), _parent(nullptr){}
};
template<class K, class V>
class RBTree
{typedef RBTreeNode<K, V> Node;
public:private:Node* _root = nullptr;
};

2:紅黑樹的插入

對于紅黑樹的插入我們一般分成兩種情況,一種是叔節點(父節點的兄弟節點)存在為紅;第二種是叔節點不存在或者為黑。

第一種情況很好處理,只需要變色就行,第二種情況需要變色加旋轉(和AVLTree樹的旋轉一樣,就不過多講解了)

下面是實現代碼

bool Insert(const pair<K, V>& kv)
{//插入邏輯(同二叉搜索樹)if (_root == nullptr){_root = new Node(kv);_root->_col = BLACK;return true;}Node* parent = nullptr;Node* cur = _root;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);cur->_col = RED;if (parent->_kv.first < kv.first){parent->_right = cur;}else{parent->_left = cur;}cur->_parent = parent;//調整邏輯while (parent && parent->_col == RED){Node* grandparent = parent->_parent;if (parent == grandparent->_left){Node* uncle = grandparent->_right;//uncle存在且為紅if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandparent->_col = RED;cur = grandparent;parent = cur->_parent;}//uncle不存在或者uncle為黑else{if (cur == parent->_right){RL(grandparent);parent->_col = BLACK;grandparent->_col = RED;}else{RR(parent);RL(grandparent);cur->_col = BLACK;grandparent->_col = RED;}break;}}else//(parent==grandparent->_right){Node* uncle = grandparent->_left;//uncle存在且為紅if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandparent->_col = RED;cur = grandparent;parent = cur->_parent;}else//uncle不存在或者為黑{if (cur == parent->_right){RL(grandparent);parent->_col = BLACK;grandparent->_col = RED;}else{RL(parent);RL(grandparent);cur->_col = BLACK;grandparent->_col = RED;}break;}}}}_root->_col = BLACK;return true;
}
//右單旋
void RR(Node* pParent)
{Node* subL = pParent->_left;Node* subLR = subL->_right;pParent->_left = subLR;if (subLR != nullptr){subLR->_parent = pParent;}subL->_right = pParent;Node* ppnode = pParent->_parent;pParent->_parent = subL;subL->_parent = ppnode;if (ppnode == nullptr){_root = subL;}else{if (ppnode->_left == pParent){ppnode->_left = subL;}else{ppnode->_right = subL;}}
}
//左單旋
void RL(Node* pParent)
{Node* subR = pParent->_right;Node* subRL = subR->_left;pParent->_right = subRL;if (subRL != nullptr){subRL->_parent = pParent;}subR->_left = pParent;Node* ppnode = pParent->_parent;pParent->_parent = subR;subR->_parent = ppnode;if (ppnode == nullptr){_root = subR;}else{if (ppnode->_left == pParent){ppnode->_left = subR;}else{ppnode->_right = subR;}}
}

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

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

相關文章

React 第三十九節 React Router 中的 unstable_usePrompt Hook的詳細用法及案例

React Router 中的 unstable_usePrompt 是一個用于在用戶嘗試離開當前頁面時觸發確認提示的自定義鉤子&#xff0c;常用于防止用戶誤操作導致數據丟失&#xff08;例如未保存的表單&#xff09;。 一、unstable_usePrompt用途 防止意外離開頁面&#xff1a;當用戶在當前頁面有…

OSI 7層模型

OSI 7層模型&#xff1a; 1、物理層&#xff08;光纖等把電腦連接起來的物理手段&#xff09; 2、數據鏈路層&#xff08;以太網&#xff0c;確認0和1電信號的分組方式&#xff0c;負責MAC地址&#xff0c;MAC地址用于在網絡中唯一標示一個網卡&#xff0c;相當于網卡的身份證…

視頻編解碼學習十一之視頻原始數據

一、視頻未編碼前的原始數據是怎樣的&#xff1f; 視頻在未編碼前的原始數據被稱為 原始視頻數據&#xff08;Raw Video Data&#xff09;&#xff0c;主要是按照幀&#xff08;Frame&#xff09;來組織的圖像序列。每一幀本質上就是一張圖片&#xff0c;通常采用某種顏色格式…

Redis學習打卡-Day1-SpringDataRedis、有狀態無狀態

Redis的Java客戶端 Jedis 以 Redis 命令作為方法名稱&#xff0c;學習成本低&#xff0c;簡單實用。Jedis 是線程不安全的&#xff0c;并且頻繁的創建和銷毀連接會有性能損耗&#xff0c;因此推薦使用 Jedis 連接池代替Jedis的直連方式。 lettuce Lettuce是基于Netty實現的&am…

告別靜態配置!Spring Boo動態線程池實戰指南:Nacos+Prometheus全鏈路監控

一、引言 1.1 動態線程池的必要性 傳統線程池的參數&#xff08;如核心線程數、隊列容量&#xff09;通常通過配置文件靜態定義&#xff0c;無法根據業務負載動態調整。例如&#xff0c;在電商大促場景中&#xff0c;流量可能瞬間激增&#xff0c;靜態線程池容易因配置不合理導…

Flask如何讀取配置信息

目錄 一、使用 app.config 讀取配置 二、設置配置的幾種方式 1. 直接設置 2. 從 Python 文件加載 3. 從環境變量加載 4. 從字典加載 5. 從 .env 文件加載&#xff08;推薦開發環境用&#xff09; 三、讀取配置值 四、最佳實踐建議 在 Flask 中讀取配置信息有幾種常見方…

【React中useCallback鉤子詳解】

useCallback 是 React 中的一個性能優化 Hook,用于緩存函數引用,避免在組件重新渲染時重復創建相同的函數,從而減少不必要的子組件渲染或副作用執行。以下是其核心要點: 1. 核心作用 函數記憶化:返回一個記憶化的回調函數,僅在依賴項變化時重新創建函數,否則復用之前的函…

【!!!!終極 Java 中間件實戰課:從 0 到 1 構建億級流量電商系統全鏈路解決方案!!!!保姆級教程---超細】

終極 Java 中間件實戰課:電商系統架構實戰教程 電商系統架構實戰教程1. 系統架構設計1.1 系統模塊劃分1.2 技術選型2. 環境搭建2.1 開發環境準備2.2 基礎設施部署3. 用戶服務開發3.1 創建Maven項目3.2 創建用戶服務模塊3.3 配置文件3.4 實體類與數據庫設計3.5 DAO層實現3.6 Se…

C#異步Task,await,async和Unity同步協程

標題 TaskawaitasyncUnity協程 Task Task是聲明異步任務的必要關鍵字&#xff0c;也可以使用Task<>泛型來定義Task的返回值。 await await是用于等待一個Task結束&#xff0c;否則讓出該線程控制權&#xff0c;讓步給其他線程&#xff0c;直到該Task結束才往下運行。 …

【USRP】在linux下安裝python API調用

UHD 源碼安裝 安裝庫 sudo apt-get install autoconf automake build-essential ccache cmake cpufrequtils doxygen ethtool \ g git inetutils-tools libboost-all-dev libncurses5 libncurses5-dev libusb-1.0-0 libusb-1.0-0-dev \ libusb-dev python3-dev python3-mako …

什么是 NoSQL 數據庫?它與關系型數據庫 (RDBMS) 的主要區別是什么?

我們來詳細分析一下 NoSQL 數據庫與關系型數據庫 (RDBMS) 的主要區別。 什么是 NoSQL 數據庫&#xff1f; NoSQL (通常指 “Not Only SQL” 而不僅僅是 “No SQL”) 是一類數據庫管理系統的總稱。它們的設計目標是解決傳統關系型數據庫 (RDBMS) 在某些場景下的局限性&#xf…

藍橋杯題庫經典題型

1、數列排序&#xff08;數組 排序&#xff09; 問題描述 給定一個長度為n的數列&#xff0c;將這個數列按從小到大的順序排列。1<n<200 輸入格式 第一行為一個整數n。 第二行包含n個整數&#xff0c;為待排序的數&#xff0c;每個整數的絕對值小于10000。 輸出格式 輸出…

wordpress自學筆記 第三節 獨立站產品和類目的三種展示方式

wordpress自學筆記 摘自 超詳細WordPress搭建獨立站商城教程-第三節 獨立站產品和類目的三種展示方式&#xff0c;2025 WordPress搭建獨立站教程#WordPress建站教程https://www.bilibili.com/video/BV1rwcteuETZ?spm_id_from333.788.videopod.sections&vd_sourcea0af3b…

智能手表藍牙 GATT 通訊協議文檔

以下是一份適用于智能手表的 藍牙 GATT 通訊協議文檔&#xff0c;適用于 BLE 5.0 及以上標準&#xff0c;兼容 iOS / Android 平臺&#xff1a; 智能手表藍牙 GATT 通訊協議文檔 文檔版本&#xff1a;V1.0 編寫日期&#xff1a;2025年xx月xx日 產品型號&#xff1a;Aurora Wat…

Linux PCI 驅動開發指南

注&#xff1a;本文為 “Linux PCI Drivers” 相關文章合輯。 英文引文&#xff0c;機翻未校。 中文引文&#xff0c;略作重排。 如有內容異常&#xff0c;請看原文。 How To Write Linux PCI Drivers 翻譯: 司延騰 Yanteng Si siyantengloongson.cn 1. 如何寫 Linux PCI 驅動 …

Python 接入DeepSeek

不知不覺DeepSeek已經火了半年左右&#xff0c;沖浪都趕不上時代了。 今天開始學習。 本文旨在使用Python調用DeepSeek的接口&#xff08; 這里寫目錄標題 一、環境準備1.1 DeepSeek1.2 Python 二、接入DeepSeek2.1 參數2.2 requests2.3 openai2.4 返回示例 一、環境準備 1.1…

Java 集合與 MyBatis 動態 SQL 實戰教程

一、Java 集合的創建與用法 在 Java 中&#xff0c;List、HashSet 和數組是常用的集合類型&#xff0c;以下是它們的創建與基本操作&#xff1a; 1. List 列表 創建方式&#xff1a; List<Integer> list new ArrayList<>(Arrays.asList(1, 2, 3)); // 可變列…

無人機避障——(運動規劃部分)深藍學院動力學kinodynamic A* 3D算法理論解讀(附C++代碼)

開源代碼鏈接&#xff1a;GitHub - Perishell/motion-planning 效果展示&#xff1a; ROS 節點展示全局規劃和軌跡生成部分&#xff1a; Kinodynamic A*代碼主體&#xff1a; int KinoAstar::search(Eigen::Vector3d start_pt, Eigen::Vector3d start_vel,Eigen::Vector3d en…

Transformer Decoder-Only 算力FLOPs估計

FLOPs和FLOPS的區別 FLOPs &#xff08;Floating Point Operations&#xff09;是指模型或算法執行過程中總的浮點運算次數&#xff0c;單位是“次”FLOPS &#xff08;Floating Point Operations Per Second&#xff09;是指硬件設備&#xff08;如 GPU 或 CPU&#xff09;每…

掌握MySQL數據庫操作:從創建到管理全攻略

1.庫的操作 1.1庫的查看 show databases; 這句語法形式是查看服務器已經存在的數據庫 注意要加分號————&#xff1b; 1.databeses是復數形式 2.大小寫都可以 前提&#xff08;數據庫已經創建或查看服務器自帶的數據庫&#xff09; 也可以查看指定的數據庫 show cre…