数据结构之B树与B+树
1. B樹
1.1 B樹的定義
這里的B樹,也就是英文中的B-Tree,一個 m 階的B樹滿足以下條件:
1.每個結點至多擁有m棵子樹;
2.根結點至少擁有兩顆子樹(存在子樹的情況下),根結點至少有一個關鍵字;
3.除了根結點以外,其余每個分支結點至少擁有 m/2 棵子樹;
4.所有的葉結點都在同一層上,B樹的葉子結點可以看成是一種外部節點,不包含任何信息;
5.有 k 棵子樹的分支結點則存在 k-1 個關鍵碼,關鍵碼按照遞增次序進行排列;
6.關鍵字數量需要滿足ceil(m/2)-1 <= n <= m-1;
1.2 B樹圖例(M=3)
B-樹的搜索,從根結點開始,對結點內的關鍵字(有序)序列進行二分查找,如果命中則結束,否則進入查詢關鍵字所屬范圍的兒子結點;重復,直到所對應的兒子指針為空,或已經是葉子結點;
1.3 B樹的特性
1.關鍵字集合分布在整顆樹中;
2.任何一個關鍵字出現且只出現在一個結點中;
3.搜索有可能在非葉子結點結束;
4.其搜索性能等價于在關鍵字全集內做一次二分查找;
5.自動層次控制;
最低搜索性能:O[Log2(N)];其中,M為設定的非葉子結點最多子樹個數,N為關鍵字總數;
???????所以B-樹的性能總是等價于二分查找(與M值無關),也就沒有B樹平衡的問題;
???????由于M/2的限制,在插入結點時,如果結點已滿,需要將結點分裂為兩個各占M/2的結點;刪除結點時,需將兩個不足M/2的兄弟結點合并;
2. B+樹
2.1 B+樹的定義
B+樹是B-樹的變體,也是一種多路搜索樹:
?????? 1.其定義基本與B-樹同,除了:
?????? 2.非葉子結點的子樹指針與關鍵字個數相同;
?????? 3.非葉子結點的子樹指針P[i],指向關鍵字值屬于[K[i], K[i+1])的子樹(B-樹是開區間);
?????? 5.為所有葉子結點增加一個鏈指針;
?????? 6.所有關鍵字都在葉子結點出現;
2.2 B+樹圖例(M=3)
B+的搜索與B-樹也基本相同,區別是B+樹只有達到葉子結點才命中(B-樹可以在非葉子結點命中),其性能也等價于在關鍵字全集做一次二分查找;
2.3 B+樹的特性
1.所有關鍵字都出現在葉子結點的鏈表中(稠密索引),且鏈表中的關鍵字恰好是有序的;
?????? 2.不可能在非葉子結點命中;
?????? 3.非葉子結點相當于是葉子結點的索引(稀疏索引),葉子結點相當于是存儲(關鍵字)數據的數據層;
?????? 4.更適合文件索引系統;
?3.? B樹與B+樹的比較
3.1 為什么B+樹比B樹更適合實際應用中操作系統的文件索引和數據庫索引?
1.B+tree的磁盤讀寫代價更低:
B+tree的內部結點并沒有指向關鍵字具體信息的指針。因此其內部結點相對B樹更小。如果把所有同一內部結點的關鍵字存放在同一盤塊中,那么盤塊所能容納的關鍵字數量也越多。一次性讀入內存中的需要查找的關鍵字也就越多。相對來說IO讀寫次數也就降低了。
2.B+tree的查詢效率更加穩定:
由于非葉子結點并不是最終指向文件內容的結點,而只是葉子結點中關鍵字的索引。所以任何關鍵字的查找必須走一條從根結點到葉子結點的路。所有關鍵字查詢的路徑長度相同,導致每一個數據的查詢效率相當。
3.B樹在提高了磁盤IO性能的同時并沒有解決元素遍歷的效率低下的問題。正是為了解決這個問題,B+樹應運而生。
B+樹只要遍歷葉子節點就可以實現整棵樹的遍歷。而且在數據庫中基于范圍的查詢是非常頻繁的,而B樹不支持這樣的操作(或者說效率太低)。
3.2 數據庫選用B+樹的原因
1.B+樹有一個最大的好處,方便掃庫,B樹必須用中序遍歷的方法按序掃庫,而B+樹直接從葉子結點挨個掃一遍就完了,B+樹支持range-query非常方便,而B樹不支持。這是數據庫選用B+樹的最主要原因。
2.mysql 底層存儲是用B+樹實現的,因為在內存中B+樹是沒有優勢的,但是一到磁盤,B+樹的威力就出來了。
B+樹是B樹的變形,它把所有的附屬數據都放在葉子結點中,只將關鍵字和子女指針保存于內結點,內結點完全是索引的功能,最大化了內結點的分支因子。不過是n個關鍵字對應著n個子女,子女中含有父輩的結點信息,葉子結點包含所有信息(內結點包含在葉子結點中,內結點沒有指向“附屬數據”的指針必須索引到葉子結點)。這樣的話還有一個好處就是對于每個結點所需的索引次數都是相等的,保證了穩定性。
3.3 B/B+Tree索引的性能對比
我們使用磁盤I/O次數評價索引結構的優劣。先從B Tree分析,根據B Tree的定義,可知檢索一次最多需要訪問h個節點。數據庫系統的設計者巧妙利用了磁盤預讀原理,將一個節點的大小設為等于一個頁,這樣每個節點只需要一次I/O就可以完全載入。為了達到這個目的,在實際實現中B-Tree在每次新建節點時,直接申請一個頁的空間,這樣就保證一個節點物理上也存儲在一個頁里,加之計算機存儲分配都是按頁對齊的,就實現了一個node只需一次I/O。
B-Tree中一次檢索最多需要h-1次I/O(根節點常駐內存),漸進復雜度為O(h)=O(logdN)。一般實際應用中,出度d是非常大的數字,通常超過100,因此h非常小(通常不超過3)。
綜上所述,用B-Tree作為索引結構效率是非常高的。而紅黑樹這種結構,h明顯要深的多。由于邏輯上很近的節點(父子)物理上可能很遠,無法利用局部性,所以紅黑樹的I/O漸進復雜度也為O(h),效率明顯比B-Tree差很多。
B+Tree更適合外存索引,原因和內節點出度d有關。從上面分析可以看到,d越大索引的性能越好,而出度的上限取決于節點內key和data的大小,由于B+Tree內節點去掉了data域,因此可以擁有更大的出度,擁有更好的性能。
轉載于:https://www.cnblogs.com/llljjc/p/10811991.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的数据结构之B树与B+树的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [Git] 001 初识 Git 与 G
- 下一篇: exam02-02