平衡二叉樹、B樹、B+樹、B*樹 理解 一通皆通

1、平衡二叉樹

 

 

  • 概念

平衡二叉樹是基於二分法的策略提高數據的查找速度的二叉樹的數據結構;

 

  • 特點:

平衡二叉樹是採用二分法思維把數據按規則組裝成一個樹形結構的數據,用這個樹形結構的數據減少無關數據的檢索,大大的提升了數據檢索的速度;平衡二叉樹的數據結構組裝過程有以下規則:

(1)非葉子節點只能允許最多兩個子節點存在。

(2)每一個非葉子節點數據分佈規則爲左邊的子節點小當前節點的值,右邊的子節點大於當前節點的值(這裏值是基於自己的算法規則而定的,比如hash值);

 

 

平衡樹的層級結構:因爲平衡二叉樹查詢性能和樹的層級(h高度)成反比,h值越小查詢越快、爲了保證樹的結構左右兩端數據大致平衡降低二叉樹的查詢難度一般會採用一種算法機制實現節點數據結構的平衡,實現了這種算法的有比如Treap、紅黑樹,使用平衡二叉樹能保證數據的左右兩邊的節點層級相差不會大於1.,通過這樣避免樹形結構由於刪除增加變成線性鏈表影響查詢效率,保證數據平衡的情況下查找數據的速度近於二分法查找;

 

 

總結平衡二叉樹特點:

(1)非葉子節點最多擁有兩個子節點;

(2)非葉子節值大於左邊子節點、小於右邊子節點;

(3)樹的左右兩邊的層級數相差不會大於1;

(4)沒有值相等重複的節點;


2、B樹(B-tree)

 

注意:之前有看到有很多文章把B樹和B-tree理解成了兩種不同類別的樹,其實這兩個是同一種樹;

 

  • 概念:

 

B樹和平衡二叉樹稍有不同的是B樹屬於多叉樹又名平衡多路查找樹(查找路徑不只兩個),數據庫索引技術裏大量使用者B樹和B+樹的數據結構,讓我們來看看他有什麼特點;

 

  • 規則:

 

(1)排序方式:所有節點關鍵字是按遞增次序排列,並遵循左小右大原則;

(2)子節點數:非葉節點的子節點數>1,且<=M ,且M>=2,空樹除外(注:M階代表一個樹節點最多有多少個查找路徑,M=M路,當M=2則是2叉樹,M=3則是3叉);

(3)關鍵字數:枝節點的關鍵字數量大於等於ceil(m/2)-1個且小於等於M-1個(注:ceil()是個朝正無窮方向取整的函數 如ceil(1.1)結果爲2);

(4)所有葉子節點均在同一層、葉子節點除了包含了關鍵字和關鍵字記錄的指針外也有指向其子節點的指針只不過其指針地址都爲null對應下圖最後一層節點的空格子;

 

最後我們用一個圖和一個實際的例子來理解B樹(這裏爲了理解方便我就直接用實際字母的大小來排列C>B>A)

 

  • B樹的查詢流程:

 

如上圖我要從上圖中找到E字母,查找流程如下

(1)獲取根節點的關鍵字進行比較,當前根節點關鍵字爲M,E<M(26個字母順序),所以往找到指向左邊的子節點(二分法規則,左小右大,左邊放小於當前節點值的子節點、右邊放大於當前節點值的子節點);

(2)拿到關鍵字D和G,D<E<G 所以直接找到D和G中間的節點;

(3)拿到E和F,因爲E=E 所以直接返回關鍵字和指針信息(如果樹結構裏面沒有包含所要查找的節點則返回null);

 

  • B樹的插入節點流程

 

定義一個5階樹(平衡5路查找樹;),現在我們要把3、8、31、11、23、29、50、28 這些數字構建出一個5階樹出來;

遵循規則:

(1)節點拆分規則:當前是要組成一個5路查找樹,那麼此時m=5,關鍵字數必須<=5-1(這裏關鍵字數>4就要進行節點拆分);

(2)排序規則:滿足節點本身比左邊節點大,比右邊節點小的排序規則;

 

先插入 3、8、31、11

 

 

再插入23、29

 

再插入50、28

 

 

  • B樹節點的刪除

 

規則:

 

(1)節點合併規則:當前是要組成一個5路查找樹,那麼此時m=5,關鍵字數必須大於等於ceil(5/2)(這裏關鍵字數<2就要進行節點合併);

(2)滿足節點本身比左邊節點大,比右邊節點小的排序規則;

(3)關鍵字數小於二時先從子節點取,子節點沒有符合條件時就向向父節點取,取中間值往父節點放;

 

特點:

B樹相對於平衡二叉樹的不同是,每個節點包含的關鍵字增多了,特別是在B樹應用到數據庫中的時候,數據庫充分利用了磁盤塊的原理(磁盤數據存儲是採用塊的形式存儲的,每個塊的大小爲4K,每次IO進行數據讀取時,同一個磁盤塊的數據可以一次性讀取出來)把節點大小限制和充分使用在磁盤快大小範圍;把樹的節點關鍵字增多後樹的層級比原來的二叉樹少了,減少數據查找的次數和複雜度;


3、B+樹

 

  • 概念

 

B+樹是B樹的一個升級版,相對於B樹來說B+樹更充分的利用了節點的空間,讓查詢速度更加穩定,其速度完全接近於二分法查找。爲什麼說B+樹查找的效率要比B樹更高、更穩定;我們先看看兩者的區別

 

  • 規則

 

(1)B+跟B樹不同B+樹的非葉子節點不保存關鍵字記錄的指針,只進行數據索引,這樣使得B+樹每個非葉子節點所能保存的關鍵字大大增加;

(2)B+樹葉子節點保存了父節點的所有關鍵字記錄的指針,所有數據地址必須要到葉子節點才能獲取到。所以每次數據查詢的次數都一樣;

(3)B+樹葉子節點的關鍵字從小到大有序排列,左邊結尾數據都會保存右邊節點開始數據的指針。

(4)非葉子節點的子節點數=關鍵字數(來源百度百科)(根據各種資料 這裏有兩種算法的實現方式,另一種爲非葉節點的關鍵字數=子節點數-1(來源維基百科),雖然他們數據排列結構不一樣,但其原理還是一樣的Mysql 的B+樹是用第一種方式實現);

(百度百科算法結構示意圖)

 

 

(維基百科算法結構示意圖)

 

  • 特點

 

1、B+樹的層級更少:相較於B樹B+每個非葉子節點存儲的關鍵字數更多,樹的層級更少所以查詢數據更快;

2、B+樹查詢速度更穩定:B+所有關鍵字數據地址都存在葉子節點上,所以每次查找的次數都相同所以查詢速度要比B樹更穩定;

3、B+樹天然具備排序功能:B+樹所有的葉子節點數據構成了一個有序鏈表,在查詢大小區間的數據時候更方便,數據緊密性很高,緩存的命中率也會比B樹高。

4、B+樹全節點遍歷更快:B+樹遍歷整棵樹只需要遍歷所有的葉子節點即可,,而不需要像B樹一樣需要對每一層進行遍歷,這有利於數據庫做全表掃描。

B樹相對於B+樹的優點是,如果經常訪問的數據離根節點很近,而B樹非葉子節點本身存有關鍵字其數據的地址,所以這種數據檢索的時候會要比B+樹快。

 

 


4、B*樹

 

  • 規則

 

B*樹是B+樹的變種,相對於B+樹他們的不同之處如下:

(1)首先是關鍵字個數限制問題,B+樹初始化的關鍵字初始化個數是cei(m/2),b*樹的初始化個數爲(cei(2/3*m))

(2)B+樹節點滿時就會分裂,而B*樹節點滿時會檢查兄弟節點是否滿(因爲每個節點都有指向兄弟的指針),如果兄弟節點未滿則向兄弟節點轉移關鍵字,如果兄弟節點已滿,則從當前節點和兄弟節點各拿出1/3的數據創建一個新的節點出來;

 

  • 特點

 

在B+樹的基礎上因其初始化的容量變大,使得節點空間使用率更高,而又存有兄弟節點的指針,可以向兄弟節點轉移關鍵字的特性使得B*樹額分解次數變得更少;

 

 


5、 總結

 

1、相同思想和策略

從平衡二叉樹、B樹、B+樹、B*樹總體來看它們的貫徹的思想是相同的,都是採用二分法和數據平衡策略來提升查找數據的速度;

 

2、不同的方式的磁盤空間利用

 

不同點是他們一個一個在演變的過程中通過IO從磁盤讀取數據的原理進行一步步的演變,每一次演變都是爲了讓節點的空間更合理的運用起來,從而使樹的層級減少達到快速查找數據的目的;

 

 

如果還沒理解的話推薦以下資料描敘的很詳細:

補充概念:

附(二分法查找):二分法查找原理 - 知乎專欄

附(B、B+、B*樹):從B樹、B+樹、B*樹談到R 樹

附(B、B+、B*樹):end&#x27;s coding life

附:B樹和B+樹的插入、刪除圖文詳解 - nullzx - 博客園

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章