面經手冊 · 第5篇《看圖說話,講解2-3平衡樹「紅黑樹的前身」》

做者:小傅哥
博客:https://bugstack.cnhtml

沉澱、分享、成長,讓本身和他人都能有所收穫!😄

1、前言

講道理5年開發,沒用過數據結構,你只是在作CRUD!程序員

不少時候大部分程序員👨‍💻‍頭疼於,查詢慢、效率低、一堆的關聯SQL,主要緣由是在程序設計上沒有作出很好的數據結構。固然也還有一部分是因爲老業務代碼,或者沒有用到一些大數據服務等。面試

數據結構、算法、設計模式,是每個程序員成長過程當中的內功心法修煉,而你的新技能用的再絢、多線程使的再六、加鎖玩的再牛🐂,也只能說明你這我的身體好,但身體好是不能抗住子彈的。只有身體+心法都好,都能縱橫捭闔算法

這一章節是結合HashMap的延展,在Jdk1.8中HashMap是使用桶數組+鏈表和紅黑樹實現,因此順着上一章節的核心原理和API功能講解後,原本這一章節想直接進入到紅黑樹,但若是想把紅黑樹學明白,就須要瞭解他的前因後果,也就是它的前身2-3樹🌲。數據庫

2、面試題

謝飛機,考你幾個簡單的知識點🦀設計模式

  1. 飛機,看你簡歷寫了解數據結構,能夠簡單介紹下2-3樹嗎?
  2. 這種樹節點有什麼特色,與你瞭解其餘的樹結構對比下?
  3. 你看這個圖,向裏面插入和刪除節點,要怎麼操做?

🤥飛機,回去等消息吧!數組

3、什麼是2-3樹

平常的學習和一部分夥伴的面試中,居然會聽👂到的是;從HashMap中文紅黑樹、從數據庫索引爲B+Tree,但問2-3樹的狀況就不是不少了。數據結構

1. 爲何使用樹結構

從最根本的緣由來看,使用樹結構就是爲了提高總體的效率;插入、刪除、查找(索引),尤爲是索引操做。由於相比於鏈表,一個平衡樹的索引時間複雜度是O(logn),而數組的索引時間複雜度是O(n)。多線程

從如下的圖上能夠對比,二者的索引耗時狀況;函數

公衆號:bugstack蟲洞棧 & 鏈表與二叉搜索樹(Binary Search Tree)時間複雜度對比

  • 從上圖能夠看到,使用樹結構有效的下降時間複雜度,提高數據索引效率。
  • 另外這個標準的樹結構,是二叉搜索樹(Binary Search Tree)。除此以外樹形結構還有;AVL樹、紅黑樹、2-3樹等

2. 二叉搜索樹退化鏈表

在樹的數據結構中,最早有點是二叉查找樹,也就是英文縮寫BST樹。在使用數據插入的過程當中,理想狀況下它是一個平衡的二叉樹,但實際上可能會出現二叉樹都一邊倒,讓二叉樹像列表同樣的數據結構。從而樹形結構的時間複雜度也從O(logn)升級到O(n),以下圖;

公衆號:bugstack蟲洞棧 & 二叉搜索樹退化鏈表

  • 二叉搜索樹的數據插入過程是,插入節點與當前樹節點作比對,小於在左,大於在右。
  • 隨着數據的插入順序不一樣,就會出現徹底不一樣的數據結構。多是一棵平衡二叉樹,也極有可能退化成鏈表的樹。
  • 當樹結構退化成鏈表之後,整個樹索引的性能也跟着退化成鏈表。

綜上呢,若是咱們但願在插入數據後又保持樹的特色,O(logn)的索引性能,那麼就須要在插入時進行節點的調整

3. 2-3樹解決平衡問題

2-3樹是什麼結構,它怎麼解決平衡問題的。帶着問題咱們繼續🤔。

2-3樹是一種很是巧妙的結構,在保持樹結構的基礎上,它容許在一個節點中能夠有兩個元素,等元素數量等於3個時候再進行調整。經過這種方式呢,來保證整個二叉搜索樹的平衡性。

這樣說可能尚未感受,來看下圖;

公衆號:bugstack蟲洞棧 & 2-3樹解決平穩問題

  • 左側是二叉搜索樹,右側是2-3平衡樹,分別插入節點四、5,觀察樹形結構變化。
  • 二叉搜索樹開始出現偏移,節點一遍倒。
  • 2-3樹經過一個節點中存放2到3個元素,來調整樹形結構,保持平衡。所謂的保持平衡就是從根節點,到每個最底部的本身點,鏈路長度一致。

2-3樹已經能夠解決平衡問題那麼,數據是怎麼存放和調整的呢,接下來咱們開始分析。

4、2-3樹使用

1. 樹結構定義和特色性質

2-3樹,讀法;二三樹,特性以下;

序號 描述 示意圖
1 2-,1個數據節點2個樹杈
2 3-,2個數據節點3個樹杈
3 三叉與兩叉的不一樣點在於,除了兩邊的節點,中間件還有一個節點。這個節點是介於二、4之間的值。
4 當隨着插入數據,會出現臨時的一個節點中,有三個元素。這時會被調整成一個二叉樹。

綜上咱們能夠總結出,2-3樹的一些性質;

  1. 2-3樹全部子葉節點都在同一層
  2. 1個節點能夠有1到2個數據,若是有三個須要調整樹結構
  3. 1個節點1個數據時,則有兩個子節點
  4. 1個節點2個數據時,則有三個子節點,且中間子節點是介於兩個節點間的值

2. 數據插入

接下來咱們就模擬在二叉搜索樹中退化成鏈表的數據,插入到2-3樹的變化過程,數據包括;一、二、三、四、五、六、7,插入過程圖以下;

公衆號:bugstack蟲洞棧 & 數據插入過程圖

以上,就是整個數據在插入過程當中,2-3樹的演化過程,接下來咱們具體講解每一步的變化;

  • α,向節點1插入數據2,此時爲了保持平衡,不會新產生分支,只會在一個節點中存放兩個節點。
  • β,繼續插入數據3,此時這個節點有三數據,一、二、3,是一個臨時區域。
  • γ,把三個數據的節點,中間節點拉起來,調整成樹形結構。
  • δ,繼續插入數據4,爲了保持樹平衡,會插在節點3的右側。
  • ε,繼續插入數據5,插入後三、四、5共用1個節點,當一個節點上有三個數據時候,則須要進行調整。
  • ζ,中間節點4向上⏫調整,調整後,1節點在左、3節點在中間、5節點在右。
  • η ,繼續插入數據6,在保持樹平衡的狀況下,與節點5公用。
  • θ ,繼續插入數據7,插入後,節點7會與當前的節點 5 6 共用。此時是一個臨時存放,須要調整。初步調整後,抽出6節點,向上存放,變爲2 4 6共用一個節點,這是一個臨時狀態,還須要繼續調整。
  • ι,由於根節點有三個數據二、四、6,則繼續須要把中間節點上移,一、3五、7 則分別成二叉落到節點2節點6上。

🇬🇷希臘字母:α(阿爾法)、 β(貝塔)、γ(伽馬)、δ(德爾塔)、ε(伊普西隆)、ζ(截塔)、η(艾塔)、θ(西塔)、ι(約塔)

3. 數據刪除

有了上面數據插入的學習,在看數據刪除其實就是一個逆向的過程,在刪除的主要包括這樣兩種狀況;

  1. 刪除了3-節點,也就是包含兩個數據元素的節點,直接刪除便可,不會破壞樹平衡。
  2. 刪除了2-節點,此時會破壞樹平衡,須要將樹高縮短或者元素合併,恢復樹平衡。

承接上面👆的例子,咱們把數據再從七、六、五、四、三、二、1順序刪除,觀察2-3樹的結構變化,以下;

公衆號:bugstack蟲洞棧 & 數據刪除過程圖

  • α,刪除節點7,由於節點7只有一個數據元素,刪除節點五、6合併,但此時破壞了2-3樹的平衡性,須要縮短樹高進行調整。
  • β,由於刪除節點後,整個樹結構不平衡,因此須要縮短樹高,調整元素。節點二、4合併,節點一、3分別插入左側和中間。
  • γ,刪除節點6,這個節點是3-節點(能夠分出3個叉的意思),刪除後不會破壞樹平衡,保持不變。
  • δ,刪除節點5,此時會破壞樹平衡,須要把跟節點4下放,與3合併。
  • ε,刪除節點4,這個節點依舊是3-節點,因此不須要改變樹結構。
  • ζ,刪除節點3,此時只有一、2節點,須要合併。
  • η ,刪除節點2,此時節點依舊是3-節點,因此不須要改變樹結構。

再看一個稍微複雜點2-3樹刪除:

公衆號:bugstack蟲洞棧 & 複雜樹刪除過程

上面👆這張圖,就一個稍微複雜點的2-3平衡樹,樹的刪除過程主要包括;

  1. 刪除4,其實須要將節點三、5合併,指向節點2,保持樹平衡。
  2. 刪除7,節點八、9合併。
  3. 刪除14,節點15上移,恢復成3-叉樹。

🤔若是有時候很差理解刪除,能夠試想下,這個要刪除的節點,在插入的時候是一個什麼效果。

4. 數據索引

相比於插入和刪除,索引的過程仍是比較簡單的,不須要調整數據結果。基本原則就是;

  1. 小於當前節點值,左側尋找
  2. 大於當前節點值,右側尋找
  3. 一直到找到索引值,中止。

🔍第一層尋找:

🔍第二層尋找:

🔍第三次尋找:

5、總結

  • 綜上講解了2-3樹🌲的核心內容,經過本章節的學習,能夠了解2-3樹是一種怎樣的數據結構、如何插入數據、刪除數據以及數據的索引,同時要知道這是一種平衡樹的結構,包括2-叉和3-叉節點以及數結構隨着數據的添加刪除調整。
  • 2-3樹是紅黑樹的演變前身,經過這一章節的學習就很容易學習紅黑樹的相關知識,在紅黑樹中添加數據進行的渲染、旋轉等來保持樹平衡。紅黑樹接近平衡
  • 數據結構方面的知識學習起來,可能會比較🤯燒腦,由於須要思考出那種模型結構和變化的過程,因此會感受困難。但這個燒腦的過程也是對學習很是有幫助的,能夠迅速建設知識凸起,當突破不理解到理解,能夠有很是多的收穫。

6、系列推薦

相關文章
相關標籤/搜索