B-Tree和B+Tree
首先,介紹一下什麽是樹(tree)
樹,就是一種順序。我們有從小到大,從大到小的順序,也自然會有“樹”這種順序。
那麽,樹,是一個怎麽樣的順序呢?
對於一列數,只能保持兩種狀態:①無序②有序
而這兩者最大的區別就是:查找的方式不同
面對無序數列,我們只能依次比較,去尋找目標值。(順序查找)
而對於有序數列,我們可以通過某種規矩去推演目標所在的位置。
而“樹”,就是我們推理的規則。
一、二叉樹(有序二叉查找樹)
規定:在一組數列中選擇一個值作為“根節點”,數列中剩下的值大於它的全部放在右側,小於它的值全部放在左邊,且所有節點最多有左右兩個子節點。
1、任意一個不為空的左子樹節點
2、任意一個不為空的右子數節點,則右子樹的值均大於於根節點的值;
3、任意節點的左右子樹也分別是二叉查找樹;
4、沒有鍵值相等的節點;
查詢方式:比較節點值和目標值,目標較大往右,較小則往左,等於則找到。
以圖中為例:
我們想要查找“5”這個目標值,需要6→3→5三步。
而如果是“3“、”7”這兩個目標值,就只需兩步。
所以,平均下來就是(3+3+3+2+2+1)/6 = 2.3
然後,我們在跟無序數列的依次查找作比較:
從最好到最壞情況:(1+2+3+4+5+6)/6 = 3.3
很明顯,以“樹”這種順序查找,要比依次查找快好多。
但是,我們說這有一種局限性,就是如果根節點沒有選擇“6”,而是選擇了最小的“2”,那麽樹就會變成這樣:
當樹變成這樣時,我們在來查找就會
(1+2+3+4+5+5)/6 = 3.16
這與“順序查找”幾乎一樣,所以樹的建立異常重要。
二、AVL樹(平衡二叉樹——Balance Tree)
在普通二叉樹的基礎上,AVL樹嚴格要求了:
所有節點的左右子樹高度差不超過1
也就是,剛開始演示的那棵“樹”。
如果,左右子樹的高度超出了要求,那麽就要用到“旋轉”
旋轉重排序
口訣:子、父換位,重新“認父”,葉子不動
來看下圖理解:
上圖就是常說的LL型,但我個人覺得討論這些“型”沒有任何意義。
第一步:找到哪兩個節點相差2,圖中為“3”與“9”;
第二步:找到在“3”這條分支上與“9”同級的節點,圖中為“6”;
第三步:將子節點與父節點換位,圖中為“6”與“8”
第四步:將多出來的節點,按照二叉樹的規定重新分配,圖中為‘7’變更為“8”的子節點。
按照,此方不論是LR、RL、RR 都能夠輕易翻轉:
如下圖的RL:
很顯然,這種二叉樹一旦變動,就相當麻煩,所以人們就又發明了一個條件不那麽苛刻的樹。
三、紅黑樹
由於,它也是一種二叉樹,所以它在具備普通二叉樹的條件外,新增:
1、每個結點要麽是紅的要麽是黑的
2、根節點是黑色的
3、每個葉節點(葉節點即樹尾端NIL指針或NULL結點)都是黑的
4、如果一個結點時紅的,那麽它的兩個兒子都是黑的
5、對於任意結點而言,其到葉節點樹尾端NIL指針的每條路徑都包含相同數目的黑結點。
為什麽,它能比AVL樹相對來說寬松一些呢?
我說下,一個困擾我很久的問題:就是"紅"、“黑”到底代表什麽?
這個其實很簡單,就是將數列分成兩組數來保持平衡,紅、黑只是記號,你要想叫“藍”、“白”樹也隨你。
那怎麽來保持平衡呢?這種平衡怎麽就比AVL松了呢?
我們,先拋開“樹”不談,我們先講一個小學知識—間隔插入
規定:公路上種了5棵樹,頭尾不能站人,人後面必須跟著一棵樹,兩樹之間可以不站人。
問,這5棵樹中最少、最多能站多少人?
這不很簡單嗎,最少 = 0人 , 最多 = (5-1)4人
那麽,在“紅黑樹”的概念上,0人平衡於4人。這就比AVL寬松多了。
關於,紅黑樹的插入、刪除會有專門一篇來分析。
四、B-Tree(Branches Tree 多路查找樹)
首先,強調一些“術語”:“高度”——從葉節點到目標節點的長度、“深度”——從根節點到目標節點的長度、“階數”——節點的最大兒子(分支)個數
網上找的例子:
拿"G"節點舉例,設根、葉節點深、高度為 0 ,“G”的深度 =2、高度 = 2、該樹階數 = 3.
所以,規定B-Tree 需滿足:
1.一個M階的B-樹,每個非葉子節點最多只有M個兒子
2、根結點的兒子數為[2, M];
3、除根結點以外的非葉子結點的兒子數為[M/2, M];
4、每個結點存放至少M/2-1(取上整)和至多M-1個關鍵字;(至少2個關鍵字)
5、非葉子結點的關鍵字個數=指向兒子的指針個數-1;
6、非葉子結點的關鍵字:K[1], K[2], …, K[M-1];且K[i] < K[i+1];
7、非葉子結點的指針:P[1], P[2], …, P[M];其中P[1]指向關鍵字小於K[1]的子樹,P[M]指向關鍵字大於K[M-1]的子樹,其它P[i]指向關鍵字屬於(K[i-1], K[i])的子樹;
8、所有葉子結點位於同一層;
由於,B-Tree的關鍵字不再像二叉樹那樣內個節點只有一個,那麽我們就不能簡單的:大於往右,小於往左了。
假設,一個節點中有 5 | 7 | 10 這三個關鍵字,那麽就是:大於10的向“最右”,大於7小於10的向“次右” ......等於關鍵字就取到,以此類推。
網上找的圖片:
下面來看下,B-Tree的插入刪除
插入:
刪除:
B+樹
為什麽要B+樹
由於B+樹的數據都存儲在葉子結點中,分支結點均為索引,方便掃庫,只需要掃一遍葉子結點即可,但是B樹因為其分支結點同樣存儲著數據,我們要找到具體的數據,需要進行一次中序遍歷按序來掃,所以B+樹更加適合在區間查詢的情況,所以通常B+樹用於數據庫索引,而B樹則常用於文件索引。
簡介
同樣的,以一個m階樹為例:
- 根結點只有一個,分支數量範圍為[2,m];
- 分支結點,每個結點包含分支數範圍為[ceil(m/2), m];
- 分支結點的關鍵字數量等於其子分支的數量減一,關鍵字的數量範圍為[ceil(m/2)-1, m-1],關鍵字順序遞增;
- 所有葉子結點都在同一層;
操作
其操作和B樹的操作是類似的,不過需要註意的是,在增加值的時候,如果存在滿員的情況,將選擇結點中的值作為新的索引,還有在刪除值的時候,索引中的關鍵字並不會刪除,也不會存在父親結點的關鍵字下沈的情況,因為那只是索引。
B樹和B+樹的區別
這都是由於B+樹和B具有這不同的存儲結構所造成的區別,以一個m階樹為例。
- 關鍵字的數量不同;B+樹中分支結點有m個關鍵字,其葉子結點也有m個,其關鍵字只是起到了一個索引的作用,但是B樹雖然也有m個子結點,但是其只擁有m-1個關鍵字。
- 存儲的位置不同;B+樹中的數據都存儲在葉子結點上,也就是其所有葉子結點的數據組合起來就是完整的數據,但是B樹的數據存儲在每一個結點中,並不僅僅存儲在葉子結點上。
- 分支結點的構造不同;B+樹的分支結點僅僅存儲著關鍵字信息和兒子的指針(這裏的指針指的是磁盤塊的偏移量),也就是說內部結點僅僅包含著索引信息。
- 查詢不同;B樹在找到具體的數值以後,則結束,而B+樹則需要通過索引找到葉子結點中的數據才結束,也就是說B+樹的搜索過程中走了一條從根結點到葉子結點的路徑
文章參考:
http://www.cnblogs.com/George1994/p/7008732.html
https://blog.csdn.net/wanghanlincsdn/article/details/61208273
B-Tree和B+Tree