B-Tree 、B+樹、B*樹
大規模資料儲存中,實現索引查詢這樣一個實際背景下,樹節點儲存的元素數量是有限的(如果元素數量非常多的話,查詢就退化成節點內部的線性查找了),這樣導致二叉查詢樹結構由於樹的深度過大而造成磁碟I/O讀寫過於頻繁,進而導致查詢效率低下。
1. B-Tree
B 樹是為了磁碟或其它儲存裝置而設計的一種多叉平衡查詢樹。許多資料庫系統都一般使用B樹或者B樹的各種變形結構,如下文即將要介紹的B+樹,B*樹來儲存資訊。
B樹與紅黑樹最大的不同在於,B樹的結點可以有許多子女,從幾個到幾千個。與紅黑樹的相同之處在於,一棵含n個結點的B樹的高度也為O(lgn),但可能比一棵紅黑樹的高度小許多,應為它的分支因子比較大。所以,B樹可以在O(logn)時間內,實現各種如插入(insert),刪除(delete)等動態集合操作。
如下圖所示,即是一棵B樹,一棵關鍵字為英語中子音字母的B樹,現在要從樹種查詢字母R(包含n[x]個關鍵字的內結點x,x有n[x]+1個子女(也就是說,一個內結點x若含有n[x]個關鍵字,那麼x將含有n[x]+1個子女)。所有的葉結點都處於相同的深度,帶陰影的結點為查詢字母R時要檢查的結點):
B 樹又叫平衡多路查詢樹。一棵m階的B樹的特性如下:
I. 樹中每個結點最多含有m個孩子(m>=2);
II. 除根結點和葉子結點外,其它每個結點至少有[ceil(m / 2)]個孩子(其中ceil(x)是一個取上限的函式);
III. 若根結點不是葉子結點,則至少有2個孩子(特殊情況:沒有孩子的根結點,即根結點為葉子結點,整棵樹只有一個根節點);
IV. 所有葉子結點都出現在同一層,葉子結點不包含任何關鍵字資訊(可以看做是外部接點或查詢失敗的接點,實際上這些結點不存在,指向這些結點的指標都為null);
V. 每個非終端結點中包含有n個關鍵字資訊: (n,P0,K1,P1,K2,P2,......,Kn,Pn)。其中: a) Ki (i=1...n)為關鍵字,且關鍵字按順序升序排序K(i-1)< Ki。 b) Pi為指向子樹根的接點,且指標P(i-1)指向子樹中所有結點的關鍵字均小於Ki,但都大於K(i-1)。 c) 關鍵字的個數n必須滿足: [ceil(m / 2)-1]<= n <= m-1。
B-Tree 資料結構:
template<class T> struct BTreeNode
{
/*實際關鍵字的個數, keyNum<m*/
int keyNum;
/*指向父節點的指標*/
BTreeNode *parent;
/*指向孩子節點的指標陣列:pChild[0],...,pChild[keyNum -1]*/
BTreeNode **pChilds;
T *key;
};
B-Tree的度:
B-Tree中每個節點能包含的關鍵字的數量有一個上界和下界。下界稱為B-Tree的最小度數。
B-Tree的高度:
a) 從B-Tree的最小度來計算
B樹上大部分操作所需的磁碟存取次數與B樹的高度成正比。下面分析B樹的最壞高度情況。如果n>=1, 則對任意一棵包含n個關鍵字、高度為h(從0開始)、最小度數t>=2的B樹有: h = logt((n+1)/2);
證明:
如果一棵B-Tree的高度為h,其根節點至少包括一個關鍵字,而其他節點至少t-1個關鍵字。深度為1的節點至少有兩個,深度為2的節點至少有2t個,深度為3的節點至少為2t2,…..,深度為h 的節點至少為2th-1,因此,
所以:h = logt((n+1)/2);
b) 從B-Tree的階數計算
若B樹某一非葉子節點包含N個關鍵字,則此非葉子節點含有N+1個孩子結點,而所有的葉子結點都在第I層,我們可以得出:
1. 因為根至少有兩個孩子,因此第2層至少有兩個結點。
2. 除根和葉子外,其它結點至少有┌m/2┐個孩子,
3. 因此在第3層至少有2*┌m/2┐個結點,
4. 在第4層至少有2*(┌m/2┐^2)個結點,
5. 在第 I層至少有2*(┌m/2┐^(l-2) )個結點,於是有: N+1 ≥ 2*┌m/2┐I-2;
6. 考慮第L層的結點個數為N+1,那麼2*(┌m/2┐^(l-2))≤N+1,也就是L層的最少結點數剛好達到N+1個,即: I≤ log┌m/2┐((N+1)/2 )+2;
所以
· 當B樹包含N個關鍵字時,B樹的最大高度為l-1(因為計算B樹高度時,葉結點所在層不計算在內),即:l - 1 = log┌m/2┐((N+1)/2 )+1。
2. B+樹
B+樹是B-樹的變體,也是一種多路搜尋樹:
其定義基本與B-樹同,除了:
1.非葉子結點的子樹指標與關鍵字個數相同;
2.非葉子結點的子樹指標P[i],指向關鍵字值屬於[K[i],K[i+1])的子樹(B-樹是開區間);
3.為所有葉子結點增加一個鏈指標;
4所有關鍵字都在葉子結點出現
B+的搜尋與B-樹也基本相同,區別是B+樹只有達到葉子結點才命中(B-樹可以在
非葉子結點命中),其效能也等價於在關鍵字全集做一次二分查詢;
B+的特性:
1.所有關鍵字都出現在葉子結點的連結串列中(稠密索引),且連結串列中的關鍵字恰好
是有序的;
2.不可能在非葉子結點命中;
3.非葉子結點相當於是葉子結點的索引(稀疏索引),葉子結點相當於是儲存
(關鍵字)資料的資料層;
4.更適合檔案索引系統;
B+樹
B*樹
是B+樹的變體,在B+樹的非根和非葉子結點再增加指向兄弟的指標;
B*樹定義了非葉子結點關鍵字個數至少為(2/3)*M,即塊的最低使用率為2/3
(代替B+樹的1/2);
B+樹的分裂:當一個結點滿時,分配一個新的結點,並將原結點中1/2的資料
複製到新結點,最後在父結點中增加新結點的指標;B+樹的分裂隻影響原結點和父
結點,而不會影響兄弟結點,所以它不需要指向兄弟的指標;
B*樹的分裂:當一個結點滿時,如果它的下一個兄弟結點未滿,那麼將一部分
資料移到兄弟結點中,再在原結點插入關鍵字,最後修改父結點中兄弟結點的關鍵字
(因為兄弟結點的關鍵字範圍改變了);如果兄弟也滿了,則在原結點與兄弟結點之
間增加新結點,並各複製1/3的資料到新結點,最後在父結點增加新結點的指標;
所以,B*樹分配新結點的概率比B+樹要低,空間使用率更高;
B*樹
--------------------- 本文來自 zhangxl 的CSDN 部落格 ,全文地址請點選:https://blog.csdn.net/sdauzxl/article/details/52234482?utm_source=copy