數據結構--紅黑樹(RBTree)

一、紅黑樹概念

1.1 什么是紅黑樹

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

2.1 紅黑樹的性質
  1. 每個結點不是紅色就是黑色
  2. 根節點是黑色的
  3. 如果一個結點是紅色的,則他的兩個孩子是黑色的,及不存在兩個連續的紅色結點
  4. 對于每個葉子結點,從該結點到其所有后代葉結點的簡單路徑,均包含相同數目的黑色節點
  5. 每個葉子結點都是黑色的(此處的葉子節點指的是空節點)

思考:為什么滿足上面的性質,紅黑樹就能保證:其最長路徑中節點個數不會超過最短路徑節點 個數的兩倍?

【解釋】:由于紅黑樹要保證每條路徑的黑色結點個數相同,且不能存在連續的兩個紅色結點,所以最短路徑就是全黑,最長路徑是一黑一紅交替,這樣紅黑樹的最長路徑的極限也只能為最短路徑的兩倍

二、紅黑樹的實現

2.1 紅黑樹結點的定義
enum Color
{RED,BLACK
};
template<class K,class V>
struct RBTreeNode
{RBTreeNode(const pair<K,V>& kv):_left(nullptr),_right(nullptr),_parent(nullptr),_kv(kv),_col(RED){}struct RBTreeNode* _left;struct RBTreeNode* _right;struct RBTreeNode* _parent;pair<K, V> _kv;Color _col;
};

思考:在結點的定義中,為什么要將結點的默認顏色給成紅色的?

【解釋】:若將結點的顏色默認為黑色,由于要求每條路徑的黑色結點個數相同,如果新插入一個結點,就會破壞這個性質,影響比較大,如果將結點的顏色默認為紅色,那么最多也就會出現兩個連續的紅色結點,只會影響一條路徑,只需要進行調整即可,影響比較小

2.2 紅黑樹的插入

1. 按照二叉搜索樹的規則將結點插入到紅黑樹中

2. 檢測插入結點后,紅黑樹的性質是否遭到破壞

因為新節點的默認顏色是紅色,因此:如果其雙親節點的顏色是黑色,沒有違反紅黑樹任何 性質,則不需要調整;但當新插入節點的雙親節點顏色為紅色時,就違反了性質三不能有連在一起的紅色節點,此時需要對紅黑樹分情況來討論:

約定:cur為當前節點,p為父節點,g為祖父節點,u為叔叔節點(因為cur與p一定為紅色,g一定為黑色,我們只需要對u進行討論)

  • 情況一:cur為紅,p為紅,g為黑,u存在且為紅(假設uncle在g的右邊)

注意:此時看到的樹可能是一顆完整的樹,也可能是一顆子樹

解決方法:

????????由于出現了連續的兩個紅色結點,我們只能將p變為黑色,因為如果cur為新增結點,將其變為黑色會破壞性質4,而將p變為黑色,會導致g的左右子樹黑色節點不同,所以需要將u也變為黑色,而g有可能只是一顆子樹,為了保證與其他路徑的黑色節點個數相同,還需要將g變為紅色如果g為根節點的話,再將其變為黑色即可。

  • 情況二:cur為紅色,p為紅色,g為黑色,u不存在或者u存在且為黑色(假設u在g的右邊)

說明:u的情況存在兩種

1.uncle不存在,那么cur一定是新增的那個結點,因為如果不是新增結點,那么cur和p至少有一個應該為黑色,不然就違反性質3了

2.uncle存在且為黑色,那么cur原來的顏色一定為黑色,現在看到cur的顏色為紅色是因為cur子樹在調整過程中將cur變為了紅色

【解決辦法】:

  • 如果cur為p的左孩子

將p變黑,g變紅,以g作為父親結點右單旋

  • 如果cur為p的右孩子

將cur變黑,g變紅,先以p為父親節點左單旋,在以g為父親節右單旋

ps:uncle為g左邊原理同上,對于旋轉不清楚的可以參考數據結構--AVL樹

2.3 代碼實現
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 (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else if(cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else{return false;}}cur = new Node(kv);if (parent->_kv.first>kv.first){parent->_left = cur;}else{parent->_right = cur;}cur->_parent = parent;while (parent && parent->_col == RED){Node* grandfather = parent->_parent;if (parent == grandfather->_left){Node* uncle = grandfather->_right;if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandfather->_col = RED;//繼續向上調整cur = grandfather;parent = cur->_parent;}else //uncle不存在或者uncle存在且為黑{if (cur == parent->_left){//      g//    p   u//  cRotateR(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else{//      g//    p   u//      cRotateL(parent);RotateR(grandfather);cur->_col = BLACK;grandfather->_col = RED;}break;}}else{Node* uncle = grandfather->_left;if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandfather->_col = RED;//繼續向上調整cur = grandfather;parent = cur->_parent;}else //uncle不存在或者uncle存在且為黑{if (cur == parent->_right){//      g//    u   p//          cRotateL(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else{//      g//    u   p//      cRotateR(parent);RotateL(grandfather);cur->_col = BLACK;grandfather->_col = RED;}break;}}}_root->_col = BLACK;return true;
}

三、紅黑樹的驗證

紅黑樹的檢測分為兩步:

1. 檢測其是否滿足二叉搜索樹(中序遍歷是否為有序序列)

2. 檢測其是否滿足紅黑樹的性質

bool IsBalance()
{if (_root->_col == RED)return false;Node* cur = _root;int RefNum = 0; //作為路徑黑色結點個數的參考while (cur){if (cur->_col == BLACK)RefNum++;cur = cur->_left;}return _IsBalance(_root,RefNum,0);
}bool _IsBalance(Node* root,int RefNum,int num)
{if (root == nullptr){//驗證每條路徑的黑色節點個數是否相同if (num != RefNum){cout << "黑色節點數不同" << endl;return false;}return true;}//驗證是否存在兩個連續的紅色節點if (root->_col == RED && root->_parent->_col == RED){cout << "連續兩個紅色" << root->_kv.first << endl;return false;}if (root->_col == BLACK)num++;return _IsBalance(root->_left, RefNum, num) && _IsBalance(root->_right, RefNum, num);
}

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

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

相關文章

openEuler-22.03-LTS安裝opengauss5.0.1(包含cm集群管理)主備

環境說明 openEuler-22.0.3-LTS opengauss5.0.1 安裝數據庫 安裝系統依賴包 yum -y install lksctp* yum -y install psmisc yum -y install bzip2 yum -y install unzip yum -y install gcc yum -y install gcc-c yum -y install perl yum -y install libxml2-devel yum …

前端(包含cocosCreator)開發環節調取后端接口時跨域,解決辦法之反向代理

/** eslint-disable */ var http require(http),httpProxy require(http-proxy),HttpProxyRules require(http-proxy-rules);// Set up proxy rules instance var port 9090 var proxyRules new HttpProxyRules({rules: {/api/(.*): https://baidu.com/$1, // 測試環境游戲…

自學VBA 設置單元格文字格式 筆記

一.設定對應單元格對應需要顯示的格式 Cells(1, 1).Font.Size 18 字體大小 Cells(1, 2).Font.Color RGB(255, 0, 0) 字體顏色 Cells(1, 3).Font.Name "黑體" 字體類型 Cells(1, 4).Font.Italic True 字體斜體 Cells(1, 5).Font.FontStyle "BOLD"…

ubuntu下gcc編譯器的安裝

.gcc編譯器的安裝 一般linux下是覆蓋含有的&#xff0c;如果沒有執行更新命令 sudo apt update gcc安裝成功&#xff0c;可以檢查一下版本 可以看出我的gcc是9.4.0版本的

驗證torch.nn.Conv2d

import os import cv2 import torch import numpy as np import random import cv2 as cv from matplotlib import pyplot as pltdef f_VerifyConv2D():"""驗證torch.nn.Conv2d&#xff0c; 并將輸入數據及權重保存到txt文件中"""x torch.randn…

SpringBoot環境隔離Profiles

前言 通常我們開發不可能只有一個生產環境&#xff0c;還會有其它的開發&#xff0c;測試&#xff0c;預發布環境等等。為了更好的管理每個環境的配置項&#xff0c;springboot也提供了對應的環境隔離的方法。 直接上干貨 知識點 激活環境方法 1&#xff0c;在application…

專用設備制造業供應商收發文件,有什么專業而輕便的方式嗎?

專用設備制造業的特點包括&#xff1a;門類廣、跨度大、科技含量高。它主要生產的是國民經濟各部門&#xff08;包括采掘、化工、冶煉、能源、醫療衛生、環保等&#xff09;所急需的重大成套設備&#xff0c;例如礦產資源井采及露天開采設備、大型火電、水電、核電成套設備、石…

教育行業文本短信VS視頻短信VS語音短信哪個好?

在教育行業中&#xff0c;文本短信、視頻短信和語音短信各有其優勢&#xff0c;選擇哪種方式更好取決于具體的應用場景和目標。 文本短信的優勢在于&#xff1a; 1.簡潔明了&#xff1a;能夠快速、直接地傳遞信息&#xff0c;對于需要快速通知或提醒的場景非常適用。 …

通過內網穿透免費部署我們的springboot+vue項目 實現跟服務器一樣的效果

前文講到通過內網穿透能夠實現遠程訪問個人電腦的靜態資源。本文將講解通過內網穿透實現遠程訪問本地的項目&#xff0c;實現跟部署到服務器一樣的效果&#xff1a;前文鏈接&#xff1a;通過內網穿透實現遠程訪問個人電腦資源詳細過程&#xff08;免費&#xff09;&#xff08;…

深度學習之卷積神經網絡理論基礎

深度學習之卷積神經網絡理論基礎 卷積層的操作&#xff08;Convolutional layer&#xff09; 在提出卷積層的概念之前首先引入圖像識別的特點 圖像識別的特點 特征具有局部性&#xff1a;老虎重要特征“王字”僅出現在頭部區域特征可能出現在任何位置下采樣圖像&#xff0c…

Python 小抄

Python 備忘單 目錄 1.語法和空格 2.注釋 3.數字和運算 4.字符串處理 5.列表、元組和字典 6.JSON 7.循環 8.文件處理 9.函數 10.處理日期時間 11.NumPy 12.Pandas 要運行單元格&#xff0c;請按 ShiftEnter 或單擊頁面頂部的 Run&#xff08;運行&#xff09;。 1.語法和空格…

三種方法進行跨服務器文件傳輸

今天需要在一個centOS服務器上編譯一個工具, 我的本地主機是ubuntu, 但是由于服務器是合規環境, 沒有文件傳輸的接口, 也不能訪問github等外網, 所以很多依賴只能下載到ubuntu然后在想辦法搞到服務器上. 這種場景有三種簡單有用的辦法, 整理一下. 方法一: 把主機配置成http ser…

6---Linux下版本控制器Git的知識點

一、Linux之父與Git的故事&#xff1a; Linux之父叫做“Linus Torvalds”&#xff0c;我們簡稱為雷納斯。Linux是開源項目&#xff0c;所以在Linux的早期開發中&#xff0c;許多世界各地的能力各異的程序員都參與到Linux的項目開發中。那時&#xff0c;雷納斯每天都會收到許許…

用ntpdate同步時間出現問題

1. 使用ntpdate同步 [rootnode ~]# ntpdate ntp.aliyun.com4 Aug 00:07:17 ntpdate[20924]: adjust time server 203.107.6.88 offset -0.001543 sec2. 查看時間 [rootnode ~]# date Thu Aug 4 00:07:46 CST 20223. 如果時間對不上 報錯信息 cna02:~ # ntpdate ntp1.aliyu…

mysql社區版最多支持多個連接并發

MySQL社區版對于并發連接數的支持并沒有一個固定的上限&#xff0c;它實際上取決于多個因素&#xff0c;包括服務器的硬件配置、MySQL的配置參數以及應用程序的設計等。 硬件配置&#xff1a;服務器的CPU、內存和磁盤I/O等硬件資源會直接影響MySQL可以處理的并發連接數。例如&a…

VMware Fusion 13.5.2 for Mac 發布,產品訂閱模式首個重大變更

VMware Fusion 13.5.2 for Mac 發布&#xff0c;產品訂閱模式首個重大變更 適用于基于 Intel 處理器和搭載 Apple 芯片的 Mac 的桌面虛擬化軟件 請訪問原文鏈接&#xff1a;https://sysin.org/blog/vmware-fusion-13/&#xff0c;查看最新版。原創作品&#xff0c;轉載請保留…

vue props接收組件數據(類型配置)

"props"接收的常見傳參類型有以下幾種&#xff1a;String&#xff1a;字符串類型&#xff0c;Number&#xff1a;數字類型&#xff0c;Boolean&#xff1a;布爾類型&#xff0c;Array&#xff1a;數組類型&#xff0c;Object&#xff1a;對象類型&#xff0c;Date&am…

文章解讀與仿真程序復現思路——中國電機工程學報EI\CSCD\北大核心《集裝箱海港級聯物流-能源耦合系統協同優化方法 》

本專欄欄目提供文章與程序復現思路&#xff0c;具體已有的論文與論文源程序可翻閱本博主免費的專欄欄目《論文與完整程序》 論文與完整源程序_電網論文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 電網論文源程序-CSDN博客電網論文源…

FPGA - GTX收發器-K碼 以及 IBERT IP核使用

一&#xff0c;前言 在FPGA - Xilinx系列高速收發器---GTX中詳細介紹了GTX的基礎知識&#xff0c;以及IP核的調用&#xff0c;下面將補充一下GTX在使用中的高速串行數據流在接收和發送時的控制與對齊&#xff08;K碼&#xff09;&#xff0c;以及高速接口GTX&#xff0c;如果G…

Springboot開發 -- Postman 調試 session 驗證 接口

當我們在開發Spring Boot應用時&#xff0c;經常會遇到帶有Session驗證的接口&#xff0c;這些接口需要用戶先登錄并獲取到Session ID&#xff08;或稱為cookie中的JSESSIONID&#xff09;&#xff0c;然后在后續的請求中攜帶這個Session ID來保持會話狀態。下面我將以一個實際…