肝了幾天我算是理解了紅黑樹

1.二叉排序樹

 

    在學習紅黑樹之前我們需要了解一下二叉排序樹,所謂二叉排序樹就是一種特殊的二叉樹,首先滿足二叉樹的性質,然後它存儲數據的方式是左邊節點比父節點的數據小,而右邊節點比父節點數據大。這樣當我們查詢一個數據時,比如我們要找數據8,先從根節點開始,8比12小所以去左子樹找,然後與5比較發現比5大那麼去右子節點此時就找到了我們需要的數據8。是不是類似於二分查找呢?只需要O(logn)就能找到數據。

 

 

 二叉搜索樹(二叉排序樹,二叉樹查找樹),他的時間複雜度取決於樹的高度,理想情況下爲O(logn),但是某些情況下會退化爲O(n),比如我們插入的數據爲10,9,8,7,6或者是1,2,3,4,5這種情況下二叉排序樹將會退化爲斜樹,相當於一個鏈表,此時查詢的時間複雜度就會變爲O(n),如下圖所示。

 

 

2.紅黑樹

 

    通過上面的例子我們可以看到即便是二叉排序樹十分的優秀,但是在某些情況下二叉排序樹的效率會大打折扣,針對這種情況科學家們衍生除了紅黑樹,只要能滿足以下性質就能讓二叉排序樹到達自平衡。

 性質1:每個節點要麼是黑色,要麼是紅色。

 性質2:根節點是黑色。

 性質3:每個葉子節點(NIL)是黑色。

 性質4:相鄰節點不能同時爲紅色,此處的相鄰是指父節點和左右任意一個子節點不能同時爲紅色,從而可以推出性質5

 性質5:每個紅色節點的兩個子節點一定都是黑色。  

    ps:紅黑樹是一個黑色平衡的樹,但是卻不是一個完美平衡的二叉排序樹,所謂的完美平衡二叉樹就是指平衡因子的絕對值小於等於1,而所謂的平衡因子指的是該節點的左子樹層數減去右子樹層數的絕對值。黑色平衡是當我們將紅黑樹中的紅色節點全部刪除時,此時你會發現都平衡因子爲小於1的。紅色節點刪除之後,有些節點就沒有父節點了,它們會直接拿這些節點的祖父節點(父節點的父節點)作爲父節點。所以,之前的二叉樹就變成了四叉樹。

 

 

3.紅黑樹的插入

 

 

 

 

 

由於場景1、2、3都比較簡單,所以就就沒有細講,可以對照着上圖的思維導圖進行了解,下面主要介紹的是場景4的,場景4都涉及到左旋,右旋以及變色的處理;首先我們要知道紅黑樹在插入節點時默認插入的節點爲紅色,這是因爲如果我們默認插入爲黑色,那麼就會導致不滿足性質5,也就是任意節點到每個葉子節點經歷的黑色節點一致。

 

插入場景4.1

 

   插入節點的父爲紅色且叔叔節點存在,並且叔叔爲紅色節點。

   處理:我們只需要將父節點和叔叔節點變爲黑色,同時祖父節點變爲紅色,如果將祖父節點變爲紅色後,此時可能出現祖父節點和自己的父節點又不平衡,所以我們還需要繼續調整。

   注意:   如果祖父節點爲根節點,此時不需要改變爲紅色,如果改變那麼就不滿足紅黑樹的性質。

 

 

插入場景4.2.1

 

    插入節點的父爲紅色,且插入節點的叔叔節點不存在或爲葉子節點(NIL)時,且插入節點爲父節點的左子樹,插入節點的父節點爲祖父節點的左子樹。

    處理:將插入節點的父改爲黑色,同時祖父節點改爲紅色,然後對父節點進行右旋,那麼我們可不可把父節點變爲紅色,插入節點和祖父節點變爲黑色,然後對父節點進行旋轉,實際上是可以的,但是由於把父變爲了紅色,那麼又會導致上面的節點可能和紅色發成衝突,那樣又要自底向上進行調整。

 

 

插入場景4.2.2

 

    插入節點的父爲紅色,且插入節點的叔叔節點不存在或爲葉子節點(NIL)時,且插入節點爲父節點的右子樹,插入節點的父節點爲祖父節點的左子樹。

    處理:首先插入節點爲父節點的右子樹時,我們可以得出插入的節點肯定是比父節點大的,實際上我們可以進行轉換,將插入節點的父節點變爲插入節點的左子樹,然後我們可以得到4.2.1的場景,然後也就是可以直接再把插入節點變爲黑色,然後左子樹和父變爲紅色進行右旋。

 

 

 

插入場景4.3.1

 

    插入節點的父節點爲紅色,且叔叔節點不存在或者叔叔節點爲葉子節點(NIL),且插入節點是父節點的右子樹,父節點是祖父節點的右子樹。

    處理:將父節點設置爲黑色,祖父節點和插入節點設置爲紅色,然後進行左旋。

 

 

 

 

插入場景4.3.2

 

    插入節點的父節點爲紅色,且叔叔節點不存在或者叔叔節點爲葉子節點(NIL),且插入節點是父節點的左子樹,父節點是祖父節點的右子樹。

    處理:首先當我們插入的節點在父節點的右邊時,我們可以得知父節點大於插入節點,那麼我們可以將父節點變爲插入節點的右子樹,然後此時插入節點就變成了原來父節點的父節點,也就得到了4.3.1的場景,此時只需要將插入節點變爲黑色,右子樹變爲紅色,插入節點的父節點變爲紅色,再進行左旋。

 

 

4.紅黑樹的刪除

 

    紅黑樹的插入相對而言比刪除操作要簡單,真正難的是紅黑樹的刪除操作,因爲涉及到查找到節點,然後要找到刪除後的位置有人來替代,以及替代後的調整。首先我們來看看二叉樹的刪除,二叉樹的刪除分爲三種情況。

   1.刪除的節點沒有子節點,直接刪除。

   2.刪除的節點只有一個子節點,將刪除節點的子節點替換成刪除節點,此時因爲我們替換掉了刪除的節點,相當於覆蓋了,那麼直接再刪除掉我們剛剛移動的節點的多餘節點,這裏不太好理解,可以參考下面的圖1所示,圖中爲刪除7節點時

   3.刪除的節點有左右子樹,找到刪除節點的後繼,然後將後繼替換爲刪除節點,再刪除需要刪除的節點,這裏的後繼就是指刪除節點右子樹中最小的葉子節點值,當然我們也可以用左子樹中最大的葉子節點值。可以參考如下圖2所示,圖中爲刪除5節點時。

 

 

 

    基於上述的刪除特點有可以我們將二叉樹轉換爲如下場景

    當爲場景2的時候,也就是刪除節點只有一個子節點時,將刪除節點替換爲子節點,然後此時我們要刪除的就是替換後的子節點,此時子節點還有左右子節點,那麼我們又可以轉換爲場景3的情況,如果只有一個節點相當於有是場景2的情況,然後一直自頂向下進行處理

    當爲場景3的時候,也就是刪除節點有左右子節點時,找到刪除節點的後繼,然後替換掉要刪除的節點,然後再刪除替換後重復的那個節點,但是如果重複的那個節點又存在右子節點,我們相當於又轉換成了場景2或者場景1的情況;需要注意的是重複節點是肯定沒有左子節點的,只有右子節點,因爲我們找的是後繼。

    下面我們就來看看紅黑樹刪除時的10種情況,如下圖所示。

 

 

刪除場景1

 

    需要替換的節點爲紅色節點

 

 

    處理:由於我們替換後我們要刪除紅色節點,但是由於刪除紅色節點並不會影響平衡,所以可以直接刪除,刪除前需要將要刪除的值和要替換的值進行覆蓋,然後把覆蓋後的顏色變爲要之前的顏色,最後再刪除重複的值。下面圖中在刪除有左右子節點的數據時,實際上找的並不是後繼,而是我們前面提到的找左子樹中最大的葉子節點,後面涉及兩個刪除帶有左右子樹節點情況時,所有動圖都是按照這種模式。

 

 

 

刪除場景2

 

    刪除節點爲黑色,且兄弟節點也爲黑色節點,父節點爲紅節點,兄弟節點沒有子節點時

 

 

    處理:將刪除節點直接刪除,然後父節點與兄弟節點交換顏色。

 

 

刪除場景3

 

    刪除節點爲黑色節點,且兄弟節點也爲黑色節點,父節點爲紅色節點,兄弟節點的左子節點爲紅色節點。

 

 

    處理:將刪除節點刪除,然後兄弟節點進行右旋,同時交換兄弟和兄弟節點左子節點的顏色,然後在對父節點進行左旋操作。

 

 

刪除場景4

 

    刪除節點爲黑色節點,且兄弟節點也爲黑色節點,父節點爲紅色節點,兄弟節點的右子節點爲紅色節點。

 

    處理:將刪除節點刪除,然後對父節點進行左旋操作。

 

 

刪除場景5

 

    刪除節點爲黑色節點,且兄弟節點也爲黑色節點,父節點爲紅色節點,兄弟節點的左右子節點都爲紅色節點。

 

 

    處理:將刪除節點刪除,對父節點進行左旋,然後再把父節點的顏色和左右子樹的節點顏色進行交換。

 

 

 

刪除場景6

 

    刪除節點爲黑色節點,兄弟節點爲紅色節點,父節點爲黑色節點,兄弟節點的兩個子節點爲黑色節點。

 

 

    處理:將刪除節點刪除,對父節點進行左旋,刪除節點的兄弟節點顏色和父節點進行交換,然後再把父節點和兄弟節點的左子節點進行顏色交換。

 

 

 刪除場景7

 

    刪除節點爲黑色節點,兄弟節點也爲黑色節點,父節點爲黑色節點,且兄弟節點沒有子節點。

 

 

    處理:將刪除節點刪除,然後把兄弟節點變爲紅色。

 

 

刪除場景8

 

    刪除節點爲黑色節點,兄弟節點也爲黑色節點,父節點爲黑色節點,且兄弟節點的子節點包含兩個紅色節點。

 

 

    處理:將刪除節點刪除,對父節點進行左旋,再將兄弟節點右子樹變爲黑色。

 

 

刪除場景9

 

    刪除節點爲黑色節點,兄弟節點也爲黑色節點,父節點爲黑色節點,且兄弟節點的子節點有一個左紅色節點。

 

 

    處理:將刪除節點刪除,對兄弟節點進行右旋,同時交換兄弟節點與兄弟節點左子樹顏色,然後再進行左旋。左旋後再將兄弟節點變爲黑色。

 

 

刪除場景10

 

    刪除節點爲黑色節點,兄弟節點也爲黑色節點,父節點爲黑色節點,且兄弟節點的子節點有一個右紅色節點。

 

 

    處理:將刪除節點刪除,對父節點進行左旋,然後對兄弟節點的右子節點變爲黑色。

 

 

    最後需要說明一點,上面的刪除情況只是針對不需要從下向上繼續調整的情況,如果需要從下向上再次調整的第一步肯定不是刪除,而是直到調整完畢以後才刪除,例如下面這個我們要刪除的就是左下角的節點,然後我們調整後並不滿足,所以要繼續調整自己的父,直到全部調整完畢後才刪除。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章