數據結構與算法目錄(http://www.javashuo.com/article/p-qvigrlkr-da.html)html
咱們都知道二叉查找樹的查找的時間複雜度是 O(logN),其查找效率已經足夠高了,那爲何還有 B 樹和 B+ 樹的出現呢?難道它兩的時間複雜度比二叉查找樹還小嗎?答案固然不是, B 樹和 B+ 樹的出現是由於另一個問題,那就是磁盤 IO。java
頁是計算機管理存儲的邏輯塊,硬件及操做系統每每將主存和磁盤存儲區分割爲連續的大小相等的塊。每一個塊都稱爲一頁(在許多操做系統中,頁大小一般爲 4K),主存和磁盤以頁爲單位交換數據。mysql
文件系統及數據庫系統的設計利用了磁盤預讀原理,將一個節點的大小設計爲一個頁,這樣每一個節點只須要一次 IO 就能夠徹底載入。算法
衆所周知,IO 操做的效率很低,那麼,當在大量數據存儲中,查詢時咱們不能一會兒將全部數據加載到內存中,只能逐一加載磁盤頁,每一個磁盤頁對應樹的節點。形成大量磁盤 IO 操做(最壞狀況下爲樹的高度)。平衡二叉樹因爲樹深度過大而形成磁盤 IO 讀寫過於頻繁,進而致使效率低下。sql
因此,咱們爲了減小磁盤 IO 的次數,就你必須下降樹的深度,將「瘦高」的樹變得「矮胖」。一個基本的想法就是:數據庫
這樣就引出來了一個新的查找樹結構 - 多路查找樹。 根據 AVL 給咱們的啓發,一顆平衡多路查找樹(B~樹)天然可使得數據的查找效率保證在 O(logN) 這樣的對數級別上。數據結構
下面來具體介紹一下 B 樹(Balance Tree),數據結構和算法
一個 m 階的 B 樹具備以下幾個特徵:B 樹中全部結點的孩子結點最大值稱爲 B 樹的階,一般用 m 表示。一個結點有 k 個孩子時,必有 k-1 個關鍵字才能將子樹中全部關鍵字劃分爲 k 個子集。性能
示例:三階 B 樹操作系統
以上圖爲例:若查詢的數值爲5:
第一次磁盤IO:在內存中定位(與1七、35比較),比17小,左子樹;
第二次磁盤IO:在內存中定位(與8、12比較),比8小,左子樹;
第三次磁盤IO:在內存中定位(與三、5比較),找到5,終止。
整個過程當中,咱們能夠看出:比較的次數並不比二叉查找樹少,尤爲適當某一節點中的數據不少時,可是磁盤 IO 的次數倒是大大減小。比較是在內存中進行的,相比於磁盤 IO 的速度,比較的耗時幾乎能夠忽略。因此當樹的高度足夠低的話,就能夠極大的提升效率。相比之下,節點中的元素多點也不要緊,僅僅是多了幾回內存交互而已,只要不超過磁盤頁的大小便可。
注意:
B+ 樹是 B 樹的變種,有着比 B 樹更高的查詢效率。下面,咱們就來看看 B+ 樹和 B 樹有什麼不一樣
有 k 個子樹的中間節點包含有 k 個元素(B 樹中是 k-1 個元素),每一個元素不保存數據,只用來索引,全部數據
都保存在葉子節點。
全部的葉子結點中包含了所有元素的信息,及指向含這些元素記錄的指針,且葉子結點自己依關鍵字的大小
自小而大順序連接。
全部的中間節點元素都同時存在於子節點,在子節點元素中是最大(或最小)元素。
下面是一棵 3 階的 B+ 樹:
B+ 樹一般有兩個指針,一個指向根結點,另外一個指向關鍵字最小的葉子結點。因些,對於 B+ 樹進行查找兩種運算:一種是從最小關鍵字起順序查找,另外一種是從根結點開始,進行隨機查找。
B+ 樹的優點在於查找效率上 ,下面咱們作一具體說明:
首先,B+樹的查找和B樹同樣,相似於二叉查找樹。起始於根節點,自頂向下遍歷樹,選擇其分離值在要查找值的任意一邊的子指針。在節點內部典型的使用是二分查找來肯定這個位置。
(1)不一樣的是,B+樹中間節點沒有衛星數據(索引元素所指向的數據記錄),只有索引,而B樹每一個結點中的每一個關鍵字都有衛星數據;這就意味着一樣的大小的磁盤頁能夠容納更多節點元素,在相同的數據量下,B+樹更加「矮胖」,IO操做更少
(2)其次,由於數據結構的不一樣,致使查詢過程也不一樣;B 樹的查找只需找到匹配元素便可,最好狀況下查找到根節點,最壞狀況下查找到葉子結點,所說性能很不穩定,而 B+ 樹每次必須查找到葉子結點,性能穩定
(3)在範圍查詢方面,B+ 樹的優點更加明顯
B樹的範圍查找須要不斷依賴中序遍歷。首先二分查找到範圍下限,在不斷經過中序遍歷,知道查找到範圍的上限便可。整個過程比較耗時。
而 B+ 樹的範圍查找則簡單了許多。首先經過二分查找,找到範圍下限,而後同過葉子結點的鏈表順序遍歷,直至找到上限便可,整個過程簡單許多,效率也比較高。
例如:一樣查找範圍 [3-11],二者的查詢過程以下:
B+ 樹相比 B 樹的優點:
參考:
天天用心記錄一點點。內容也許不重要,但習慣很重要!