說到HashMap,就必定要說到紅黑樹,紅黑樹做爲一種自平衡二叉查找樹,是一種用途較廣的數據結構,在jdk1.8中使用紅黑樹提高HashMap的性能,今天就來講一說紅黑樹,上一講已經給出插入平衡的調整操做,這一講就說說更爲複雜的刪除平衡操做。html
限於篇幅,本文只對紅黑樹的基礎進行說明,暫不涉及源碼部分,大部分摘抄自維基百科,這裏也貼出對應連接:數據結構
維基百科(中文):https://zh.wikipedia.org/wiki...性能
維基百科:https://en.wikipedia.org/wiki...spa
筆者這裏會根據維基百科的講解作些說明,方便初學者理解。.net
在正式進入紅黑樹的刪除說明以前,想下二叉搜索樹中的刪除是如何作的?code
參照二叉搜索樹的刪除調整原理:htm
若是須要刪除的節點有兩個兒子,那麼問題能夠被轉化成刪除另外一個只有一個兒子的節點的問題(爲了表述方便,這裏所指的兒子,爲非葉子節點的兒子)。對於二叉查找樹,在刪除帶有兩個非葉子兒子的節點的時候,咱們要麼找到它左子樹中的最大元素、要麼找到它右子樹中的最小元素,並把它的值轉移到要刪除的節點中(如在這裏所展現的那樣)。咱們接着刪除咱們從中複製出值的那個節點,它一定有少於兩個非葉子的兒子。由於只是複製了一個值(沒有複製顏色),不違反任何性質,這就把問題簡化爲如何刪除最多有一個兒子的節點的問題。它不關心這個節點是最初要刪除的節點仍是咱們從中複製出值的那個節點。
那麼紅黑樹中會出現哪些狀況呢?blog
對於第一種狀況,咱們能夠找到刪除節點的後繼節點,將值替換,而後刪除後繼節點,這樣保證了該樹仍然是一棵二叉樹,可是在刪除後繼節點時可能破壞了紅黑樹的特性,故須要進行調整。強調一下,紅黑樹中的葉子節點指的都是NIL節點。遞歸
這樣來看,被刪除的節點必定有一個右子樹,可能爲NIL也可能爲非空子樹,接下來就具體看看狀況。ip
1.若是刪除節點E爲紅色,則E子節點F則必爲黑色(紅黑樹特性),這種狀況只有在E的兩個節點都爲葉子節點時纔會發生。故刪除以後紅黑樹平衡不用調整。能夠自行畫圖驗證:
2.若是刪除節點E爲黑色,F爲紅色,這種狀況下,F節點有兩個葉子節點(需保證紅黑樹特性,黑色路徑需保持一致)則F放置到E處時只須要變色就可使得紅黑樹平衡
3.若是刪除節點E爲黑色,F也爲黑色,這種狀況只有在E的兩個節點都爲葉子節點時纔會發生。參考上邊狀況1的驗證。這裏刪除了一個黑色節點,紅黑樹平衡被破壞(黑色路徑不一樣了),須要進行調整
針對3這裏就又會有如下幾種狀況:
N爲刪除的位置節點,如今被刪除的節點的子節點取代(這裏子節點對應上邊的F,即刪除後,N的位置爲葉子節點),N爲黑色,P爲N的父母,S爲P的右子,SL表明S的左子,SR表明S的右子。
S必不爲葉子節點,反推下,若是爲葉子節點,在未刪除以前P的兩邊黑色路徑就不一致了(未刪除以前是P->E->F這種,自行畫圖理解)。注意,下面列舉的狀況都是在刪除E節點後,子節點取代E造成的狀況,在此基礎上進行紅黑樹的調整。按照順序每種狀況進行判斷處理
。注意每種狀況處理以後會從新標記,以適應下次狀況的對比調整,而且下列過程只以第一次調用時說明,遞歸調用下列順序過程時將葉子節點當成一個已經平衡的局部紅黑樹便可。和以前的插入平衡調整相似,每次都是局部化調整。
第一種狀況:若是N爲根節點,不須要調整平衡了,原有樹只有一個非葉子節點,兩個葉子節點,刪除了根節點,至關於刪除了紅黑樹。繼續第二種狀況判斷。
第二種狀況:若是N(這裏是葉子節點NIL)是其父P的左子節點,S爲紅色,P必爲黑色,參照下圖,反轉P和S的顏色,而後在P處向左旋轉,將S轉換爲N的祖父母。這裏N處的黑色路徑少一個,還未平衡。N是其父P的右子節點參照類似處理。SL標記爲新的S繼續以N,P,S這塊局部樹進行處理。繼續第三種狀況處理。
第三種狀況:若是P,S和S的孩子都是黑色,左圖顯示了出現的狀況,在N替換掉以前的父節點後造成的狀態,這裏從新繪製S爲紅色,變爲右圖,在這個局部中知足平衡紅黑樹的特性4和5,可是經過P節點的黑色路徑相比原有結構減小了1,還須要進行調整,需從新進行平衡。這裏從新平衡即從第一種狀況再次順序執行,以P節點進行從新平衡,至關於以P爲新的N,黑色路徑少1,再次進行平衡調整。不知足當前狀況,再繼續執行第4種狀況處理。
第四種狀況:若是S和S的孩子是黑色,但P是紅色的。在這種狀況下,咱們只需交換S和P的顏色。這不會影響經過S的路徑上的黑色節點數量,但它確實會在經過N的路徑上添加一個黑色節點數,從而彌補這些路徑上已刪除的黑色節點。將達到紅黑樹平衡。不知足當前狀況,則繼續第五種狀況的處理。
第五種狀況:若是S是黑色,S的左孩子是紅色,S的右孩子是黑色,N是其父母的左孩子。在這種狀況下,咱們在S處右轉,這樣S的左邊孩子就成了S的父母和N的新兄弟。而後咱們交換S及其新父母的顏色。全部路徑仍然有相同數量的黑色結點,可是P的左子樹由於刪除一個節點致使黑色路徑少1,還未徹底平衡。這裏進行調整主要是爲了知足第六種狀況,繼續第六種狀況的處理。
第六種狀況: 若是S是黑色,S的右子是紅色,N是其父P的左子。在這種狀況下,咱們向左旋轉P,這樣S成爲P和S的右子的父親。而後,咱們交換P和S的顏色,並使S的右子節點變黑。比較刪除前與N替換調整後的屬性,知足4和5,與刪除前是一致的。
刪除操做相對插入操做以後的平衡要複雜的多,不過按照狀況一步步處理也是比較明瞭的,一樣爲了方便初學者理解,從上邊的過程咱們也能夠發現,在一次局部平衡調整中,最多進行3次旋轉操做,我這裏再進行一個流程梳理,幫助各位更好的理解紅黑樹的刪除操做。
到此關於紅黑樹的基礎已經介紹完畢,下一章我將就JDK源碼中的TreeNode進行講解說明,看一看紅黑樹是如何在源碼中實現的。
參考資料: