一.爲何要有紅黑樹這種數據結構?
咱們知道ALV樹是一種嚴格按照定義來實現的平衡二叉查找樹,因此它查找的效率很是穩定,爲O(log n),因爲其嚴格按照左右子樹高度差不大於1的規則,插入和刪除操做中須要大量且複雜的操做來保持ALV樹的平衡(左旋和右旋),所以ALV樹適用於大量查詢,少許插入和刪除的場景中數據結構
那麼假設如今假設有這樣一種場景:大量查詢,大量插入和刪除,如今使用ALV樹就不太合適了,由於ALV樹大量的插入和刪除會很是耗時間,那麼咱們是否能夠下降ALV樹對平衡性的要求從而達到快速的插入和刪除呢?性能
答案確定是有的,紅黑樹這種數據結構就應運而生了(由於ALV樹是高度平衡的,因此查找起來確定比紅黑樹快,可是紅黑樹在插入和刪除方面的性能就遠遠不是ALV樹所能比的了)spa
二.紅黑樹的簡介
紅黑樹是一種特殊的二叉查找樹,每一個結點都要儲存位表示結點的顏色,或紅或黑3d
紅黑樹的特性:blog
1)每一個結點或紅或黑get
2)根結點是黑色it
3)空葉子結點是黑色class
4)若是一個結點是紅色,那麼它的子節點是黑色效率
5)從任意一個結點出發到空的葉子結點通過的黑結點個數相同(好比下圖中80到任意一個空葉子結點通過的黑結點都是3)原理
示意圖:(紅黑樹首先是一顆搜索樹,因此左子樹點小於根結點,右子樹大於根節點,等於根結點的按照本身的須要放左邊和右邊都是能夠的)(紅黑樹不只是一顆搜索樹仍是一顆非嚴格的平衡樹)
圖1
如今有個問題:紅黑樹是怎麼經過上面5條性質保證任意結點到空的葉子結點的全部路徑中,沒有一條路徑會大於其餘路徑的兩倍的呢?(換句話說就是它是如何確保任何一個結點的左右子樹的高度差不會超過兩者中較低那個的一倍的呢?)
先結合紅黑樹的5個性質分析一下紅黑樹的一些操做,咱們可能就明白了!
三.紅黑樹的基本操做之旋轉
紅黑樹的基本操做是添加和刪除,在對紅黑樹進行添加和刪除以後,都會用到旋轉方法,爲何呢?道理很簡單,由於添加或者刪除紅黑樹中的結點以後,紅黑樹就發生了變化,可能不知足上面的5條性質了,這個時候就須要經過旋轉操做來保證它依舊是一棵紅黑樹,旋轉分爲左旋和右旋(旋轉操做僅僅只是用來調節結點的位置的,就是爲了知足紅黑樹的性質5)
1.左旋
圖2
左旋是將X的右子樹繞X逆時針旋轉,使得X的右子樹成爲X的父親,同時修改相關結點的引用,旋轉以後,要求二叉查找樹的屬性依然知足
2.右旋
圖3
右旋是將X的左子樹繞X順時針旋轉,使得X的左子樹成爲X的父親,同時注意修改相關結點的引用,旋轉以後要求仍然知足搜索樹的屬性
四.紅黑樹的基本操做之添加元素
添加操做宏觀過程:首先將紅黑樹看成一顆查找樹同樣將結點插入,而後將結點着爲紅色,最後經過旋轉和從新着色的方法使之從新成爲紅黑樹
將新加入的結點塗成紅色的緣由:
1)不違背紅黑樹的性質5:從任意一個結點出發到空葉子結點,通過的黑色結點個數相同
2)按照紅黑樹的性質4咱們知道紅黑樹中黑結點的個數至少是紅結點個數的兩倍,因此新增結點的父親結點是黑結點的機率比較大,若是新增結點的父節點爲黑色,那麼此時不須要再去進行任何調整操做,所以效率很高,因此新結點應該塗成紅色,少違背一條性質,意味着咱們後續的旋轉和從新着色操做會簡單不少。如今咱們來看看新增一個紅色的結點會違背紅黑樹的5條性質中的哪些?
1)每一個結點或紅或黑
2)根結點是黑色
3)空葉子結點是黑色
4)若是一個結點是紅色,那麼它的子節點是黑色
5)從任意一個結點出發到空的葉子結點通過的黑結點個數相同
1.顯然沒有違背
2.根據查找樹的特定,插入操做很差改變根結點,因此也沒有違背
3.插入的確定不是空葉子結點,因此也沒有違背
4.有可能違背!!!
5.插入結點塗成紅色就是爲了避免違背第5條性質
如今咱們來分析一下新增的結點(紅色)插入以後可能面臨的幾種狀況,以及他們的處理措施
1.插入的結點爲根結點:將新插入的紅色結點變成黑色結點,知足根結點爲黑色結點的要求!
2.父親結點爲黑色結點:這個時候不須要進行任何調整操做,此時的樹仍然是一顆標準的紅黑樹
3.父親結點爲紅色結點的狀況下,叔叔結點爲紅色結點(不用考慮左右)
解決方案:將叔叔和父親結點改成黑色,爺爺結點改成紅色,未完
而後又將爺爺結點看成插入結點看待,一直進行上面的操做,直到當前結點爲根結點,而後將根結點變成黑色
原圖:
圖4
插入一個125的結點:
圖5
如今125結點和130結點都是紅色的,顯然違背了規則4,因此將新插入結點的父親130結點和插入結點的叔叔結點150變成黑色,並將新插入結點的爺爺結點140變成紅色,圖以下:
圖6
而後又將140結點看成新插入結點處理(由於140結點和新插入結點面臨的狀況都是同樣的:和父親結點都是紅色),也就是作以下處理:將140結點的父親結點120和140的叔叔結點60變成黑色結點,將140結點的爺爺結點變成紅色,由於遍歷到了根結點,要知足根結點是黑色的性質要求,因此又將140的爺爺結點也就是根結點變成黑色,圖以下:
圖7
到這裏,爲新插入結點125所作的某些結點從新着色的操做就完成了,如今該樹是標準的紅黑樹了!
4.新插入的結點的父親結點爲紅色,其叔叔結點爲黑色,
1)父親結點爲爺爺結點的左孩子,新插入結點爲父節點的左孩子(左左狀況)
2)父親結點爲爺爺結點的右孩子,新插入結點爲父親結點的右孩子(右右狀況)
上述兩種狀況都是同一個處理辦法
好比下圖,新插入結點爲25,其父親結點30爲紅色,其叔叔結點爲空黑色葉子結點,且新插入結點和其父節點都是左孩子:
圖8
咱們將其父親結點和爺爺結點顏色互換,而後針對爺爺結點進行一次左旋,圖以下:
圖9
如今這顆樹徹底知足紅黑樹的5個性質了(最好本身對照5個性質看一下)
如今又一個問題,咱們爲何要進行旋轉?
假設咱們只將新增結點的父親結點和其爺爺結點的顏色互換了,圖以下:
圖10
咱們發現上述兩條到葉子結點的路徑通過的黑色結點數量不同!!!,因此它不知足紅黑樹的第5條性質,因此這就是咱們旋轉的意義所在!!!(由於不管你這麼旋轉都沒有改變結點顏色,改變的是結點的位置,而這位置改變恰好能使得樹知足紅黑樹的第5條性質!)
5.新插入的結點的父親結點是紅色,其叔叔結點是黑色
1)插入結點是右結點,父節點是左結點
2)插入結點是左結點,父親結點是右結點
上述兩種狀況都是同一個處理辦法
好比下圖,新插入結點是126,其父結點125爲紅色,其叔叔結點爲空的黑色結點,並且插入結點是右結點,父結點是左結點
圖11
咱們將父親結點125看做當前結點進行左旋,旋轉結果以下:
圖12
如今咱們的當前結點是125,如今125的處境和上面的狀況4是同樣的(父節點爲紅,叔叔結點爲黑,插入結點爲左結點,父親結點也爲左孩子)如今咱們繼續按照狀況4的處理辦法處理上述狀況(措施和狀況4同樣,父親結點和爺爺結點互換顏色,而後針對爺爺結點進行左旋),處理後狀況以下:
圖13
如今樹就是一顆標準的紅黑樹了!
咱們如今總結一下插入結點面臨的幾種狀況以及採起的措施:
1.樹爲空,插入的結點爲根結點
直接將插入的結點變成黑色
2.父親結點爲黑色結點
不須要任何操做
3.父親結點爲紅色結點的狀況下:
3.1 叔叔結點也爲紅色結點
將叔叔和父親結點改成黑色,爺爺結點改成紅色,未完,而後又將爺爺結點看成插入結點看待,一直進行上
面的操做,直到當前結點爲根結點,而後將根結點變成黑色
3.2 叔叔結點爲黑色結點的狀況下:
3.2.1 (父親結點爲左孩子,插入結點也爲左孩子)||(父親結點爲右孩子,插入結點也爲右孩子)
將父親結點和爺爺結點的顏色互換,而後針對爺爺結點進行一次左旋
3.2.2 (父親結點爲左孩子,插入結點爲右孩子)||(父親結點爲右孩子,插入結點爲左孩子)
針對父結點進行左旋,此時左旋後的狀況一定是3.2.1的狀況,而後按照3.2.1的狀況處理
如今咱們來討論一下,爲何插入的狀況只有上面這些:
1.爺爺結點爲紅色結點的狀況下,父親結點只能爲黑色(紅黑樹的性質4),處理操做:上面狀況2
2.爺爺結點爲黑色的狀況下,父親結點和叔叔結點:能夠爲紅色,也能夠爲黑色
2.1 父親結點爲黑,叔叔結點爲黑:處理操做:上面狀況2
2.2 父親結點爲黑,叔叔結點爲紅:處理操做:上面狀況2
2.3 父親結點爲紅,叔叔結點爲紅:處理操做:上面狀況3.1
(上面3種狀況都是不用考慮左右的)
2.4 父親結點爲紅,叔叔結點爲黑:
2.4.1 父親結點爲左孩子,叔叔結點爲左孩子:處理操做:上面狀況3.2.1
2.4.2 父親結點爲右孩子,叔叔結點爲右孩子:處理操做:上面狀況3.2.1
2.4.3 父親結點爲左孩子,插入結點爲右孩子:處理操做:上面狀況3.2.2
2.4.4 父親結點爲右孩子,插入結點爲左孩子:處理操做:上面狀況3.2.2
總結:能夠發現咱們沒有遺漏任何狀況,全部可能面臨的狀況咱們都處理了
五.紅黑樹之刪除結點
先說一個刪除結點的過程原理:首先將紅黑樹看成一個二叉查找樹,將該結點從二叉查找樹種刪除,而後經過一些列從新着色操做等一系列措施來修正該樹,使之從新成爲一顆紅黑樹
刪除結點其實很容易,難的是如何使得刪除結點後的樹從新成爲一個紅黑樹
咱們能夠根據刪除結點N的兒子個數分爲三種狀況:
1.刪除結點沒有兒子
2.刪除結點有1個兒子
3.刪除結點有2個兒子
接下來咱們又能夠對以上三種狀況繼續進行細分
一.刪除結點沒有兒子的狀況:
1)刪除結點爲紅色
2)刪除結點爲黑色,其兄弟結點沒有兒子
3)刪除結點爲黑色,其兄弟結點有一個孩子不空,而且該孩子爲右孩子
4)刪除結點爲黑色,其兄弟結點有一個孩子不空,而且該孩子爲左孩子
5)刪除結點爲黑色,其兄弟結點有兩個孩子,並且兄弟結點爲紅色
6)刪除結點爲黑色,其兄弟結點有兩個孩子,並且兄弟結點爲黑色
二.刪除結點只有一個兒子的狀況:
1)刪除結點爲黑色,其惟一的兒子結點爲紅色(一定是紅色,要否則不符合紅黑樹的第5條性質)
2)刪除結點爲紅色,其兒子結點只能爲黑:紅黑樹中不存在這種狀況,要否則沒法知足紅黑樹第5條性質
三.刪除結點有兩個兒子的狀況:
如今咱們就具體分析一下面臨不一樣的操做到達該這麼操做:
一.刪除結點沒有兒子的狀況:
1)刪除結點爲紅色
直接刪除,好比下圖,想要刪除130結點
圖14
直接刪除130結點,結果圖以下:
圖15
由於刪除的是紅色結點,不會影響紅黑樹第5條性質,因此能夠直接刪除
2)刪除結點爲黑色,其兄弟結點沒有兒子
這種狀況下其兄弟結點也確定是黑色的(要知足紅黑樹第5條性質),假設如今要刪除的是150這個結點,原圖以下:
圖16
先刪除結點150,而後將兄弟結點126變成紅色,父親結點140變成黑色,結果以下:
圖17
這樣作的目的是爲了知足紅黑樹的第5條性質,要否則根到最右邊的葉子結點通過的黑色結點只有3個,而其餘路徑有4個
3)刪除結點爲黑色,其兄弟結點有一個孩子不空,而且該孩子和兄弟結點在同一邊(同爲左子樹或者同爲右子樹)
假設如今要刪除的結點爲110,其兄弟結點140只有一個孩子150,並且都是右子樹,知足上述條件,原圖以下:
圖18
先把須要刪除的結點110刪除,而後這個時候須要交換兄弟結點140和父親結點120的顏色,而且把父親結點120塗成黑色,把兄弟結點的子節點150塗成黑色
1.若是兄弟結點和兄弟結點的兒子都在右子樹的話:對父親結點進行左旋
2.若是兄弟結點和兄弟結點的兒子都在左子樹的話:對父親結點進行右旋
上圖是第一種狀況,因此對父結點120進行左旋,結果以下:
圖19
經過對某些結點從新着色和旋轉,又將該樹變成了一個標準的紅黑樹了
4)刪除結點爲黑色,其兄弟結點有一個孩子不空,而且該孩子和兄弟結點不在同一邊(右左或者左右的狀況)
(這種狀況下,兄弟結點的兒子50結點只能爲紅色,要否則知足不了紅黑樹的第5條性質)
假設咱們如今要刪除的結點是80結點,其兄弟結點只有一個兒子,並且兄弟結點和兄弟結點的兒子是左右的狀況(兄弟結點爲左結點,兄弟結點的兒子爲右結點),符合上述要求,原圖以下:
圖20
如今咱們先將須要刪除的80結點刪除,而後將兄弟結點和兄弟結點的兒子結點顏色互換
若是兄弟結點是左子樹,兄弟結點的兒子結點是右子樹:對兄弟結點進行左旋
若是兄弟結點是右子樹,兄弟結點的兒子結點是左子樹:對兄弟結點進行右旋
上圖的狀況是進行左旋,也就是對兄弟結點30進行左旋,結果以下圖:
圖21
注意!!,如今尚未結束變換,咱們發現變換以後的紅黑樹狀況和狀況3中的狀況很類似,兄弟結點50和兄弟結點的子節點30處在同一邊,咱們能夠按照狀況3的處理辦法進行處理:
交換兄弟結點50和父親結點60的顏色,把父親結點60和兄弟結點的子節點30塗成黑色
1.若是兄弟結點和兄弟結點的兒子都在右子樹的話:對父親結點進行左旋
2.若是兄弟結點和兄弟結點的兒子都在左子樹的話,對父親結點進行右旋
上圖的狀況是第2中,因此對父親結點60進行右旋,結果以下:
圖22
5)刪除結點爲黑色,其兄弟結點有兩個孩子,兄弟結點爲黑色並且兩個孩子結點也爲黑色
如今咱們假設要刪除的結點是130結點,其兄弟結點有兩個孩子(能夠把空的葉子結點當作黑色的兒子結點),並且兄弟結點和兄弟結點的兒子結點都是黑色,符合上述狀況,原圖以下:
圖23
先直接刪除須要刪除的結點130,而後將父親結點140和兄弟結點150顏色互換便可,結果以下:
圖24
6)刪除結點爲黑色,其兄弟結點有兩個孩子,並且兄弟結點爲紅色
假設咱們要刪除的結點是110,其兄弟結點140爲紅色並且有兩個孩子,原圖以下:
圖25
咱們先交換兄弟結點140和父親結點120的顏色
1.被刪除的元素爲左子樹:對父親結點左旋
2.被刪除的元素爲右子樹:對父親結點右旋
上圖的狀況是第一種狀況,因此咱們對父親結點140進行左旋,按照上面操做以後(未完),結果以下:
圖26
咱們發現完成上述操做以後樹還不是一個標準的紅黑樹(到葉子結點的一條路徑黑色結點只有3個,而其餘的路徑有4個),咱們發現如今紅黑樹的狀況又和狀況5的很像,因此咱們按照狀況5的作法繼續:
咱們要須要刪除的結點尚未被刪除(我特地留到最後刪除的,就是爲了在這裏表示父親結點是誰的父親結點...),如今咱們將父親結點120和兄弟結點130的顏色互換便可,結果以下:
圖27
咱們如今對刪除結點沒有兒子結點的6種刪除狀況進行一下總結:
刪除結點沒有兒子結點:
1)刪除結點爲紅色:
直接刪除
2)刪除結點爲黑色,其兄弟結點沒有兒子:
兄弟結點變紅,父親結點變黑
3)刪除結點爲黑色,其兄弟結點有一個孩子不空,而且該孩子和兄弟結點在同一邊(同爲左子樹或者同爲右子樹):
1.不論是括號中那種狀況,先交換兄弟結點和父親結點的顏色,而且把父親結點和兄弟結點的子結點塗成黑色
2.1若是兄弟結點和兄弟結點的兒子都在右子樹的話:對父親結點進行左旋
2.2若是兄弟結點和兄弟結點的兒子都在左子樹的話:對父親結點進行右旋
4)刪除結點爲黑色,其兄弟結點有一個孩子不空,而且該孩子和兄弟結點不在同一邊(右左或者左右的狀況):
1.先將兄弟結點和兄弟結點的兒子結點顏色互換
2.1若是兄弟結點是左子樹,兄弟結點的兒子結點是右子樹:對兄弟結點進行左旋
2.2若是兄弟結點是右子樹,兄弟結點的兒子結點是左子樹:對兄弟結點進行右旋
3.將後續變換按照第3條處理
5)刪除結點爲黑色,其兄弟結點有兩個孩子,兄弟結點爲黑色並且兩個孩子結點也爲黑色:
1.將父親結點和兄弟結點顏色互換
6)刪除結點爲黑色,其兄弟結點有兩個孩子,並且兄弟結點爲紅色:
1.將兄弟結點和父親結點的顏色互換
2.1 被刪除的元素爲左子樹:對父親結點左旋
2.2 被刪除的元素爲右子樹:對父親結點右旋
3.將後續變換按照第5條進行處理
以上6種狀況討論的都是刪除結點沒有兒子的狀況(空葉子結點不算兒子結點)
如今咱們來看看刪除結點僅有一個兒子結點的狀況!
二.刪除結點僅有一個兒子結點的狀況
1)刪除結點爲黑色,兒子結點不管左右均可以
好比咱們要刪除的結點是120結點,刪除結點爲黑色,惟一的兒子結點130爲紅色(必須是紅色,否則違背紅黑樹第5條性質)原圖以下:
圖28
咱們將須要刪除的結點120刪除,而後將子節點130塗黑放到被刪除結點120的位置,結果以下:
圖29
2)刪除結點爲紅色:其兒子結點只能爲黑,紅黑樹中不存在這種狀況,要否則沒法知足紅黑樹第5條性質
總結一下刪除結點只有一個兒子的狀況:
1)刪除結點爲黑色,兒子結點不管左右均可以
將兒子結點塗成黑色放到被刪除結點的位置
下面咱們來看看刪除結點有兩個兒子結點的狀況
三.刪除結點有兩個兒子結點
找到刪除結點的右子樹中最左的結點,兩兩值交換,而後刪除結點的狀況就變成了上面兩種狀況中的一種了
1.刪除結點只有一個兒子的狀況
2.刪除結點沒有兒子的狀況
好比下圖
圖30
假設要刪除的結點是120,先找到結點120右子樹中最左的結點125,交換二者的值,圖以下:
圖31
如今120仍然是要刪除的結點,咱們發現刪除結點120沒有一個兒子,並且其兄弟結點也沒有兒子,那麼其對應的狀況爲:
2)刪除結點爲黑色,其兄弟結點沒有兒子:
兄弟結點變紅,父親結點變黑
通過上面的變形,結果以下:
圖32
通過變換,該樹變成了一顆標準的紅黑樹
因此當刪除結點右兩個兒子結點的時候,咱們只須要按照搜索二叉樹的刪除方法替換刪除值,這樣就能夠將狀況變成刪除結點沒有兒子結點或者1個兒子結點的狀況處理了。