前戲紅黑樹,對不少童鞋來講,是既熟悉又陌生。熟悉是由於在校學習期間,準備面試時,這是重點。而後通過多年的荒廢,現在已經忘記的差很少了。若是正在看文章的你,立刻快要畢業,面臨着找工做的壓力;又或者你以爲須要將這塊知識從新複習一遍;又或者只是看看,那麼恭喜你,賺到了。那麼我將帶領你們從新認識下紅黑樹,用簡單的語言,搞懂紅黑樹。面試 在學習紅黑樹以前,我們須要先來理解下二叉查找樹(BST)。算法 二叉查找樹要想了解二叉查找樹,咱們首先看下二叉查找樹有哪些特性呢?編程 1, 左子樹上全部的節點的值均小於或等於他的根節點的值設計模式 2, 右子數上全部的節點的值均大於或等於他的根節點的值網絡 3, 左右子樹也必定分別爲二叉排序樹數據結構 咱們來看下圖的這棵樹,他就是典型的二叉查找樹架構 那問題來了,爲何必定要這種結構呢?換句話說這樣的結構有什麼好處呢?咱們就來查找下值爲10的節點。它怎麼一步步的找到這個節點的?步驟是怎樣的?接着往下看。數據結構和算法 1, 查找到根節點9,看下圖:性能 2, 因爲10大於9的,因此查找到右孩子13,看下圖:學習 3, 又由於10是小與13的,因此查找到左孩子11,看下圖: 4, 這一步相比不用說了你們也都知道了,找到了左孩子,而後發現正好是10 。剛好是正要尋找的值。 可能又有童鞋會問,這不是二分查找的思想嗎?確實,查找所需的最大次數等同於二叉查找樹的高度。固然在插入節點的時候,也是這種思想,一層一層的找到合適的位置插入。可是二叉查找樹有個比較大的缺陷,並且這個缺陷會影響到他的性能。咱們先來看下有一種狀況的插入操做: 若是初始的二叉查找樹只有三個節點,以下圖: 咱們依次插入5個節點:7,6,5,4,3,。看下圖插入以後的圖: 看出來了嗎?有沒有以爲很彆扭,若是根節點足夠大,那是否是「左腿」會變的特別長,也就是說查找的性能大打折扣,幾乎就是線性查找了。 那有沒有好的辦法解決這個問題呢?解決這種屢次插入新節點而致使的不平衡?這個時候紅黑樹就登場了。 紅黑樹紅黑樹就是一種平衡的二叉查找樹,說他平衡的意思是他不會變成「瘸子」,左腿特別長或者右腿特別長。除了符合二叉查找樹的特性以外,還具體下列的特性: 1. 節點是紅色或者黑色 2. 根節點是黑色 3. 每一個葉子的節點都是黑色的空節點(NULL) 4. 每一個紅色節點的兩個子節點都是黑色的。 5. 從任意節點到其每一個葉子的全部路徑都包含相同的黑色節點。 看下圖就是一個典型的紅黑樹: 不少童鞋又會驚訝了,天啊這個條條框框也太多了吧。沒錯,正式由於這些規則,才能保證紅黑樹的自平衡。最長路徑不超過最短路徑的2倍。 當插入和刪除節點,就會對平衡形成破壞,這時候須要對樹進行調整,從而從新達到平衡。那什麼狀況下會破壞紅黑樹的規則呢? 1,咱們看下圖: 向原來的紅黑樹插入值爲14的新節點,因爲父節點15是黑色節點,因此這種狀況沒有破壞結構,不須要作任何的改變。 2,向原樹插入21呢?,看下圖: 因爲父節點22是紅色節點,所以這種狀況打破了紅黑樹的規則4,必須做出調整。那麼究竟該怎麼調整呢?有兩種方式【變色】和【旋轉】分爲【左旋轉】和【右旋轉】。 【變色】: 爲了符合紅黑樹的規則,會把節點紅變黑或者黑變紅。下圖展現的是紅黑樹的部分,須要注意節點25並不是根節點。由於21和22連接出現紅色,不符合規則4,因此把22紅變黑: 但這樣仍是不符合規則5,因此須要把25黑變紅,看下圖: 你覺得如今結束了?天真,由於25和27又是兩個連續的紅色節點(規則4),因此須要將27紅變黑。 終於結束了,都知足規則了,舒服多了。 【左旋轉】 也就是逆時針旋轉兩個節點,使父節點被本身的右孩子取代,而本身成爲本身的左孩子,聽起來嚇死人,直接看圖吧: 【右旋轉】 順時針旋轉兩個節點,使得本身的父節點被左孩子取代,而本身成爲本身的右孩子,看不懂直接看圖吧: 看起來這麼複雜,到底怎麼用呢?確實很複雜,咱們講下典型的例子,你們參考下: 以剛纔插入21節點的例子: 首先咱們須要作的是變色,把節點25以及下方的節點變色: 因爲17和25是連續的兩個紅色節點,那麼吧節點17變黑嗎?這樣是不行的,你想這樣一來不就打破了規則4了嗎,並且根據規則2,也不可能吧13變成紅色。變色已經沒法解決問題了,因此只能進行旋轉了。13當成X,17當成Y,左旋轉試試看: 因爲根節點必須是黑色,因此須要變色,結果以下圖: 繼續,其中有兩條路徑(17-)8->6->NULL)的黑色節點個數不是3,是4不符合規則。 這個時候須要把13當作X,8當作Y,進行右旋轉: 最後根據規則變色: 這樣一來,咱們終於結束了,通過調整以後符合規則。 那咱們費這麼大力氣,這麼複雜,這東西用在哪裏,有哪些應用呢? 其實STL中的map就是用的紅黑樹。 總結: 紅黑色的大致思想就是上面描述的那樣,裏面還有不少狀況要考慮,本文只是簡單的講述思想,你們有興趣能夠去百度上看各類狀況的考慮。謝謝你們的支持! 喜歡個人文章的話,就關注我吧!在本頭條號的置頂文章中有【文章分類】包含:[C++進階篇系列][高級網絡編程篇系列][Linux系統篇系列][C++基礎知識篇][協議篇系列][數據結構和算法系列][設計模式系列]不要只收藏和轉發哦,軟件架構師成長必經之路。 |