寫在前面
紅黑樹,對不少童鞋來講,是既熟悉又陌生。學校中學過,只瞭解大概;工做中不怎麼使用,但面試又是重點。每次須要查看紅黑樹內容時都很難以更生動形象的方式來理解其內容。沒錯,本文內容就是要解決這個問題,用簡單的語言,搭配靜圖和動圖(利用大腦圖形記憶方式),讓你對紅黑樹有更深刻的瞭解和更清晰的記憶,但願小夥伴們再次遇到紅黑樹的問題不至於頭大,建議讀該文章姿式: 打開兩個頁面,一個頁面看圖片和內容,一個頁面看公式,像玩魔方同樣,多玩幾回就明白了html
經過工具 (公衆號回覆「工具」—>那些能夠提升效率的工具—>紅黑樹) 動態感覺紅黑樹的轉換過程git
俺家司令買完東西后,我倆常常會發生這樣的一段對話:
司令:你猜我買的這個多少錢? 我: 1000 司令: 高了 我: 500 司令: 低了: 我: 750 ...... 直到最後猜中面試
這樣說你們應該已經猜到了是「二分查找法」,經過這個例子我想要引出的是 樹,來看圖片算法
程序中的樹實際上是咱們平常看到的樹的倒影,或者發揮一下想象,倒影也能夠是樹根多線程
二叉查找樹
二叉查找樹,Binary Search Tree 「BST」,要想了解二叉查找樹,咱們首先看下二叉查找樹有哪些特性呢?併發
- 某節點的左子樹節點值僅包含小於該節點值
- 某節點的右子樹節點值僅包含大於該節點值
- 左右子樹每一個也必須是二叉查找樹 看個圖就輕鬆理解上面三句話的意思了:
上圖,結合二叉查找樹的三條約束來看,很是好,沒有什麼問題。再來看一個圖,依舊符合上面三條約束,感受有問題嗎?工具
- 這是一個走路一米六,一米八的樹
- 這是一個畸形的樹,大風一掛極可能被折斷的樹 從程序的角度來講這個樹不夠平衡,查找次數或時間複雜度 O(h)可能會隨着一條腿長無限增加
理科生在高中學習生物時學過一個關鍵字「去除頂端優點」,經過去除植物頂端優點,側芽會迅速生長,慢慢變得強壯和平衡, 紅黑樹其實就是去除二叉查找樹頂端優點的解決方案,從而達到樹的平衡學習
紅黑樹
紅黑樹,Red-Black Tree 「RBT」是一個自平衡(不是絕對的平衡)的二叉查找樹(BST),樹上的每一個節點都遵循下面的規則:動畫
- 每一個節點都有紅色或黑色
- 樹的根始終是黑色的 (黑土地孕育黑樹根,😄)
- 沒有兩個相鄰的紅色節點(紅色節點不能有紅色父節點或紅色子節點,並無說不能出現連續的黑色節點)
- 從節點(包括根)到其任何後代NULL節點(葉子結點下方掛的兩個空節點,而且認爲他們是黑色的)的每條路徑都具備相同數量的黑色節點
瞬間懵逼?瞭解一下印象就行,開始玩魔方都是要照着魔方公式一點點玩的,多玩幾回就熟悉了。紅黑樹也同樣,紅黑樹有兩大操做:spa
- recolor (從新標記黑色或紅色)
- rotation (旋轉,這是樹達到平衡的關鍵) 咱們會先嚐試 recolor,若是 recolor 不能達到紅黑樹的 4 點要求,而後咱們嘗試 rotation,其實紅黑樹的關鍵玩法就是弄清楚 recolor 和 rotation 的規則,接下來看看詳細的算法公式吧 千萬彆着急記憶公式,有圖示會逐步說明,就像魔方同樣,多玩幾回就懂了: 假設咱們插入的新節點爲 X
-
- 將新插入的節點標記爲紅色
-
- 若是 X 是根結點(root),則標記爲黑色
-
- 若是 X 的 parent 不是黑色,同時 X 也不是 root:
- 3.1 若是 X 的 uncle (叔叔) 是紅色
- 3.1.1 將 parent 和 uncle 標記爲黑色
- 3.1.2 將 grand parent (祖父) 標記爲紅色
- 3.1.3 讓 X 節點的顏色與 X 祖父的顏色相同,而後重複步驟 二、3
話很少說,看下圖
跟着上面的公式走:
- 將新插入的 X 節點標記爲紅色
- 發現 X 的 parent (P) 一樣爲紅色,這違反了紅黑樹的第三條規則「不能有兩個連續相鄰的紅色節點」
- 發現 X 的 uncle (U) 一樣爲紅色
- 將 P 和 U 標記爲黑色
- 將 X 和 X 的 grand parent (G) 標記爲相同的顏色,即紅色,繼續重複公式 二、3
- 發現 G 是根結點,標記爲黑色
- 結束
剛剛說了 X 的 uncle 是紅色的狀況,接下來要說是黑色的狀況
-
- 若是 X 的 parent 不是黑色,同時 X 也不是 root:
- 3.2 若是 X 的 uncle (叔叔) 是黑色,咱們要分四種狀況處理
- 3.2.1 左左 (P 是 G 的左孩子,而且 X 是 P 的左孩子)
- 3.2.2 左右 (P 是 G 的左孩子,而且 X 是 P 的右孩子)
- 3.2.3 右右 (和 3.2.1 鏡像過來,剛好相反)
- 3.2.4 右左 (和 3.2.2 鏡像過來,剛好相反) 當出現 uncle 是黑色的時候咱們第一步要考慮的是 旋轉 ,這裏先請小夥伴不要關注紅黑樹的第 4 條規則,主要是爲了演示如何旋轉的,來一點點看,不要看圖就慌,有解釋的😜:
左左狀況
這種狀況很簡單,想象這是一根繩子,手提起 P 節點,而後變色便可
左右
左旋: 使 X 的父節點 P 被 X 取代,同時父節點 P 成爲 X 的左孩子,而後再應用 左左狀況
右右
與左左狀況同樣,想象成一根繩子
右左
右旋: 使 X 的父節點 P 被 X 取代,同時父節點 P 成爲 X 的右孩子,而後再應用 右右狀況
你說的動圖在哪裏,你個大騙子,彆着急,如今就爲小夥伴們奉上動圖演示,來講明公式的使用:
案例一
插入 10,20,30,15 到一個空樹中
- 向空樹中第一次插入數字 10,確定是 root 節點
- root 節點標記成黑色
- 向樹中插入新節點 20,標記爲紅色
- 20 > 10,並發現 10 沒有葉子節點,將新節點 20 做爲 10 的右孩子
- 向樹中插入新節點 30,標記爲紅色
- 30 > 10,查找 10 的右子樹,找到 20
- 30 > 20,繼續查找 20 的右子樹,發現 20 沒有葉子節點,將值插在此處
- 30 和 20 節點都爲紅色,30 爲右孩子,20 也爲右孩子,觸發了 右右狀況
- 經過一次旋轉,提起 20 節點
- 20 節點是根結點,標記爲黑色
- 向樹中插入新節點 15,標記爲紅色
- 經過比對大小和判斷是否有葉子節點,最終插值爲 10 節點的右孩子
- 15 和 10 節點都爲紅色,15 的 uncle 節點 30 也爲紅色
- 按照公式,將 15 的 parent 10 和 uncle 30 更改成黑色
- 讓 15 節點 grand parent 20 的顏色與 15 節點的顏色同樣,變爲紅色
- 20 爲根結點,將其改成黑色
繼續插入其餘節點只不過反覆應用上面的公式,上面應用到的紅黑樹工具,能夠暫停動畫效果,一幀一幀的看紅黑樹的轉換過程,這樣經過練習,查看公式,觀察變化三管齊下,紅黑樹的入門理解應該徹底再也不是問題了
靈魂追問
- jdk 1.8 HashMap 中有使用到紅黑樹,你知道觸發條件是什麼嗎?有讀過源碼是如何 put 和 remove 的嗎?
- 這裏講的是紅黑樹的 insert,delete 又是什麼規則呢?
- 哪些場景能夠應用紅黑樹?
- 你瞭解各類樹的時間複雜度嗎?
- 留個小做業,應用工具將 [10 70 32 34 13 56 32 56 21 3 62 4 ] 逐個插入到樹中,理解紅黑樹 recolor 和 rotation 的轉換規則
提升效率工具
[center]
推薦閱讀
歡迎持續關注公衆號:「日拱一兵」
- 前沿 Java 技術乾貨分享
- 高效工具彙總
- 面試問題分析與解答
- 技術資料領取
後續文章會爲你講解各類時間空間複雜度,以及多線程,ElasticSearch 等問題
以讀偵探小說思惟輕鬆趣味學習 Java 技術棧相關知識,本着將複雜問題簡單化,抽象問題具體化和圖形化原則逐步分解技術問題,技術持續更新,請持續關注......
原文出處:https://www.cnblogs.com/FraserYu/p/11235948.html