紅黑樹是一種近似平衡的二叉查詢樹,它能夠確保任何乙個節點的左右子樹的高度差不會超過二者中較低那個的一陪。具體來說,紅黑樹是滿足如下條件的二叉查詢樹(binary search tree):
每個節點要麼是紅色,要麼是黑色。
根節點必須是黑色
紅色節點不能連續(也即是,紅色節點的孩子和父親都不能是紅色)。
對於每個節點,從該點至null(樹尾端)的任何路徑,都含有相同個數的黑色節點。
在樹的結構發生改變時(插入或者刪除操作),往往會破壞上述條件3或條件4,需要通過調整使得查詢樹重新滿足紅黑樹的條件。
左旋
右旋
在討論紅黑樹的插入操作之前必須要明白,任何乙個即將插入的新結點的初始顏色都為紅色。這一點很容易理解,因為插入黑點會增加某條路徑上黑結點的數目,從而導致整棵樹黑高度的不平衡。但如果新結點的父結點為紅色時(如下圖所示),將會違反紅黑樹的性質:一條路徑上不能出現相鄰的兩個紅色結點。這時就需要通過一系列操作來使紅黑樹保持平衡。
(1)父黑
直接插入,不影響樹結構。
(2.1)父紅叔紅
無需進行旋轉操作,只要將父和叔結點變為黑色,將祖父結點變為紅色即可。但由於祖父結點的父結點有可能為紅色,從而違反紅黑樹性質。此時必須將祖父結點作為新的判定點繼續向上(迭代)進行平衡操作。
新插入的21的顏色置為紅色
將其雙父變黑,上層再2遍紅(迭代)
顯然整棵樹都平衡了。但是還有有問題。根節點顏色成了紅色,這個好辦,直接設定根節點顏色為黑色即可。於是整棵樹平衡。
(2.2)父紅叔黑
需要旋轉和變色操作。
如插入7:
明顯插入的節點7已經破壞平衡,並且父親是紅色,叔叔是nil(黑色),這個時候我們又該怎麼辦呢?
這個時候假設我們能把6放到1的位置,1變成6的左孩子,並且交換1和6的顏色,那麼是不是平衡了呢?
是不是很神奇呢?其實這個操作的名字叫做樹的旋轉。注意:設定顏色不是旋轉的一部分。上面採用的就是樹的左旋,以1作為旋轉點(需要旋轉的子樹的根節點)
刪除操作相比插入更加複雜。
第一:先看最簡單情況,即刪除紅色節點。刪除紅色節點,不影響紅黑樹平衡性質,如圖:
只需要刪除紅色節點,不需要進行調整,因為不影響紅黑樹的性質。 黑色節點沒有增多也沒有減少。
注意:以下幾種單支情況在平衡的紅黑樹中不可能出現。
因為上述的情況,紅黑樹處於不平衡狀態。(破壞到null,黑色節點數目相同)
所以,平衡狀態下紅黑樹要麼單支黑-紅,要麼有兩個子節點。
第二:刪除單支黑節點(情況複雜,以後研究)。
紅黑樹原理
若左子樹不為空,則左子樹上所有節點的值都小於根節點的值 若右子樹不為空,則右子樹上所有節點的值都大於根節點的值 且左右子樹都為二叉搜尋樹 查詢 必須從根節點開始查詢 如果值比根節點大則查詢右子樹,否則左子樹,直到找到節點 插入 與查詢類似 逐個節點對比,直到找到滿足條件的null,就插入到相應位置 ...
核心紅黑樹使用範例
核心中的紅黑樹只是提供了乙個管理機制,並沒有提供具體的使用介面。需要使用者根據自己的使用環境去定義和實現自己的關鍵字 char,uchar,int,uint等型別 操作。這樣可以更加靈活。像核心中的鍊錶,hash表的 都是這種思想。1 struct mytype 2 78 struct mytype...
紅黑樹的原理,雙紅缺陷,雙黑缺陷
引入紅黑樹的目的是為了實現在維護bst平衡的同時,盡量控制拓撲結構調整的次數,即最好做到每次動態操作後只有o 1 次的拓撲調整。紅黑樹的規則 1 樹根必須是黑色 2 外部節點必須為黑色 3 其餘節點 紅節點只能有黑孩子,即不能出現相鄰的父子兩代都為紅色 4 外部節點到根 所有外部節點的黑深度相同。在...