一、滿足下面幾個條件的二叉搜尋樹,稱為紅黑樹:
1. 任何乙個節點都被著色――紅色或是黑色。
2. 根節點是黑色的。
3. 所有的nil節點都看成黑色(nil節點是就是乙個假想的或是無實在意義的節點,所有應該指向null的指標,都看成指向了nil節點。包括葉節點的子節點指標或是根節點的父指標)。
4. 如果乙個節點是紅色的,那麼它的子節點一定是黑色的。
5. 對於任何乙個節點而言,從該節點到它的子孫節點中的nil節點路徑中,所包含的黑節點個數相同。
二、黑高度的定義:
從任何乙個節點,向下到底部的路徑中,包含的黑節點的個數,稱為這個節點的黑高度。從紅黑樹的第5條性質可以看出,黑高度是唯一的、確定的。
只要同時滿足紅黑樹的這些條件,就一定會有「紅黑樹可以保證任何兩條從根部到樹葉的路徑節點個數相差不超過2倍」這個平衡的性質。
我們可以假設,如果存在兩條路徑l和s,l比s長兩倍以上(s路徑上有n個節點,l上有大於2n個節點)。可知,s的黑高度最大只可能是n,那麼根據第5條性質,l的黑高度也大也只可能是n,也就是,l路徑上一定有超過n個紅色節點(因為節點不是黑的就必定是紅的)。所以,肯定會有兩個以上的紅色節點是相鄰的。這就與第4個條件矛盾了。所以,紅黑樹可以保證任何兩條從根部到樹葉的路徑節點個數相差不超過2倍。
紅黑樹的高度h<2lg(n+1)(這個在《演算法導論》13.1節中有證明)。也就是說,紅黑樹的操作的時間複雜度是o(lgn)的。
二叉搜尋樹的操作時間複雜度,取決於樹高h,因此,我們當然就希望h盡量地小以提高操作的效率。從直觀上就可以發現,二叉搜尋樹各子樹的規模越平均,它的高度就會越小。所以在應用中,一般都會將二叉搜尋樹實現成一種平衡樹,以保證最差時間複雜度為o(lgn)。紅黑樹就是其中的一種,應用得很廣泛(sgi stl的set和map就是基於紅黑樹來實現,linux核心中也用到這個資料結構)
紅黑樹是二叉搜尋樹的一種。它與普通二叉搜尋樹不同的是,紅黑樹的每個節點都附加了另乙個屬性――顏色,可以是紅色,也可以是黑色。通過對於每條路徑上節點顏色的規則進行限定,紅黑樹可以保證任何兩條從根部到樹葉的路徑節點個數相差不超過2倍。所以,紅黑樹是一種近似平衡的二叉搜尋樹。
紅黑樹的查詢、最大值、最小值、前趨、後繼等操作,與普通的二叉搜尋樹沒有什麼區別。插入和刪除操作需要重新實現。僅僅用普通的二叉搜尋樹的插入和刪除動作,可能會破壞紅黑樹本身的一些性質,因此,需要進行額外的處理。這些額外的處理主要是改變樹節點的顏色,或是改變樹的結構。
三、樹的旋轉
改變樹的結構,主要是用旋轉。旋轉有兩種,左旋和右旋,下面是這兩種旋轉的:
這種旋轉的操作,是在二叉搜尋樹的區域性對樹的結構進行調整的一種方式,經過旋轉之後,二叉搜尋樹的性質是不會發生改變的。如下圖:
向紅黑樹插入節點,先將需要插入的節點著成紅色,用普通二叉搜尋樹的方法將這個節點插入到樹中,然後再想辦法把被破壞的紅黑性質恢復。(將新插入的節點顏色著成紅色,呆以儘量減少對紅黑性質的破壞,恢復起來也容易。因為插入紅色節點的話,那麼被破壞的部分會在區域性,考慮的問題也就比較少,恢復過程也容易形成遞迴,詳細見下文說明)
我們考慮下,如果乙個紅色節點(下文稱用z指向它)被插入到樹中,那麼有哪些紅黑性質可能被破壞呢?只有第2條(根節點是黑色的)以及第4條(紅色節點的子節點一定是黑色節點),其它都不會被破壞。
如果插入的節點的父節點是黑色的,那麼不需要做任何調整,這紅黑樹是正常的。如果父節點是紅色,或沒有父節點(也就是插在了樹根的位置),那麼就要進行調整以保證紅黑樹是正確的。
首先對第4 條進行分析,我們知道,插入乙個新的節點,這個節點肯定會被放到樹的底部成為乙個葉節點(參考普通二叉樹的插入過程),那麼這個紅色節點就沒有可能和自己的子節點同色(因為葉節點的子節點是nil節點,都是黑色的),如果第4條被破壞的話,肯定是z指向的節點的父節點是紅色的。因此,為了使分析和解決更加容易和清晰,我們在對樹進行調整以恢復紅黑特性時,始終使得z總是指向相鄰紅色的節點中的子節點(指標z可能會向上公升到樹的中部或根部)。基於這個做法,我們可以知道,如果是第2條被破壞了的話,也就是z指向根節點了,那麼第4條肯定就符合了(因為z的父節點是nil,黑色的),因此對第2條性質的恢復變得很簡單,只需要被根從紅色變為黑色即可。這時,所有性質都會被滿足了(因為是根節點,所以根節點被著為黑色時,所有路徑都黑高會統一加1,也就是第5條不會被破壞,操作之後的紅黑樹仍然是正確的)。好了,現在只留下第4條性質的恢復的問題了。
如果第4條被破壞了,也就是說,z的父節點是紅色的,那麼,說明,z一定有祖父節點,而且是黑色的(否則插入前原樹就有問題,又或是調整時的方法不正確)。因此可以把問題放到以z的祖父節點為根節點的子樹內進行解決,這樣可以把調整的範圍最小化,而且這也是有可能的:只要不改變這子樹的黑高度,那麼就不會對樹的其它部分產生影響。我們要做的就是在這個子樹範圍內把紅黑性質調整回來。再看子樹的根是否與其父節點同為紅色,是的話,就再次用前面所說的去解決它,一直向上遞迴到紅黑性質被恢復為止。
四、紅黑樹的節點插入
對第4條性質的恢復,根據z的父節點是z的祖節點的左子節點還是右子節點,分為兩組對稱的情況,每組有3種情況。下面我們只對其中一組進行說明,以z的父節點是z祖節點的左子節點為例:
rbt-insert3
第一種:z的「叔父」節點是紅色。
rbtree1
如上圖所示,在這種情況下,將父、叔節點都著為黑色,再將子樹根節點著為紅色,那麼子樹的黑高度沒有發生改變,而且紅黑性質得得到了調整。此時,再將z指向子樹的根節點,向上遞迴恢復紅黑特性。
第二種:z的「叔父」節點是黑色的,z的父節點的左子節點。
如上圖,將z的父節點與祖節點進行一次右旋,並把父節點著黑色,原來的祖節點著紅色。這些子樹的紅黑特性得到了恢復,而且子樹的黑高度沒有變化。另外,由於子樹根節點已經是黑色了(這個節點不會出現父子同為紅色的問題了),所以不必再向上遞迴了,此時整個樹的紅黑特性都已經是正確的了。
第三種:z的「叔父」節點是黑色的,z的父節點的右子節點。
如上圖,將z本身與其父節點進行一次左旋,讓z指向原來的父節點,就可以調整為情況二,而情況二已經得到解決。
這樣,紅黑樹的節點插入問題就得到了解決。
紅黑樹(插入)
紅黑樹的插入操作相對刪除操作比較簡單。紅黑樹要滿足 任一節點至null的任何路徑,所含黑節點數必須相同。所以,為了滿足此性質,插入節點應該為紅色。如果插入節點的父親為黑色,則不需要進行調整,若為紅色,有三種情況需要討論。1.父節點為紅色,叔節點為紅色 對於這種情況,同時改變父 叔節點顏色為黑色,並將...
紅黑樹插入
一 什麼是紅黑樹 紅黑樹 red black tree 是一種自平衡二叉查詢樹,是在電腦科學中用到的一種資料結構,典型的用途是實現關聯陣列。紅黑樹是一棵二叉搜尋樹,它在每個結點上增加了乙個儲存位來表示結點的顏色,可以是red或black。一棵紅黑樹是滿足下面紅黑性質的二叉搜尋樹 1 每乙個結點或是紅...
紅黑樹 插入
嗯。總是忘。再查以前做的筆記也好麻煩。於是將以前做的筆記重新整理 再整合其他優質內容,存到部落格上吧,方便以後看。紅黑樹是許多 平衡 搜尋樹的一種,可以保證在最壞情況下基本動態操作集合的時間複雜度為o lgn 1 紅黑樹的性質 以上節選自 演算法導論 第三版 首先可以看到,紅黑樹是一顆二叉搜尋樹,那...