本文參考自《大話數據結構》數據結構
通常而言,咱們都是在內存中處理數據,但假如咱們要操做的數據集很是大,內存沒法處理了,在這種狀況下對數據的處理須要不斷地從硬盤等存儲設備中調入或調出內存頁面。學習
對外存設備的讀寫,效率並不樂觀。爲了下降對外存設備的訪問次數,咱們須要新的數據結構來處理這個問題。以前學習過的樹,一個結點能夠有多個孩子,但它自身只能存儲一個元素。二叉樹限制更多,只有兩個孩子結點。在元素很是多時,要麼樹的度很是大(結點擁有子樹的個數的最大值),要麼樹的高度很是大,若是咱們要查找某一元素,必須屢次訪問外存設備,這迫使咱們要打破每個結點只能存儲一個元素的限制,引入多路查找樹的概念。指針
多路查找樹,其每個結點的孩子數能夠多於兩個,且一個結點能夠存儲多個元素。因爲它是查找樹,全部元素之間存在某種特定的排序關係。blog
2-3 樹是擁有如下性質的多路查找樹:排序
每個結點都具備兩個孩子(稱爲 2 結點)獲三個孩子(稱爲 3 孩子)索引
一個 2 結點包含一個元素和兩個孩子(或沒有孩子),左子樹包含的元素小於該元素,右子樹包含的元素大於該元素內存
一個 3 結點包含一大一小兩個元素和三個孩子(或沒有孩子),左子樹包含的元素小於較小元素,右子樹包含的元素大於較大元素,中間子樹包含介於兩個元素之間的元素效率
2-3 樹中全部的葉子結點都在同一層次上基礎
對於 2-3 樹,查找某一元素的方法與二叉排序樹同樣。要判斷一個元素是否存在,咱們先將待查找元素和根節點比較,若是它和其中任意一個相等,那查找命中;不然根據比較的結果來選擇查找的方向。擴展
要對 2-3 樹插入元素,若是是一顆空樹,直接建立一個 2 結點便可,若是不是空樹,則要考慮如下狀況:
插入結點到一個 2 結點,可直接將 2 結點轉換爲 3 結點
插入結點到一個 3 結點,其父結點爲 2 結點
若是命中查找結束於 3 結點,先臨時將其成爲 4 結點,把待插入元素添加到其中,而後將 4 結點轉化爲 3 個 2 結點,中間的結點成爲左右結點的父結點,並與父結點爲合併。
插入結點到一個 3 結點,其父結點爲 3 結點
插入元素後一直向上分解臨時的 4 節點,直到遇到 2 節點的父節點變成 3 節點再也不分解爲止。若是達到樹根節點仍是 4 節點,則分解根節點,此時樹高加一(只有分解根節點纔會增長樹高)。
對於 2-3 樹的刪除,若是對前面插入的理解到位的話,就不是難事了。相比於插入,刪除的狀況較多,若是逐一介紹就太浪費時間了,總的來講它是有規律的。
2-3-4 樹其實就是 2-3 樹的概念擴展,它多了一個 4 結點。一個 4 結點包含小中大三個元素和四個孩子(或沒有孩子),左子樹包含小於最小元素的元素;第二子樹包含大於最小元素,小於第二元素的元素;第三子樹包含大於第二元素,小於最大元素的元素;右子樹包含大於最大元素的元素。
B 樹是一種平衡的多路查找樹,2-3 樹和 2-3-4 樹都是 B 樹的特例,結點所擁有的最大孩子樹稱爲 B 樹的階,所以,2-3 樹是 3 階 B 樹,2-3-4 樹是 4 階 B 樹。
一個 m 階的 B 樹具備以下屬性:
B 樹的插入和刪除和 2-3 樹或 2-3-4 樹是相似的,只不過階數可能會很大而已。B 樹能夠幫助咱們減小內存與外存之間數據的頻繁交換,假設一顆 B 樹的階是 1001,高度爲 2,它能夠存儲超過 10 億個關鍵字。咱們只要讓根結點持久保留在內存中,那麼尋找一個關鍵字至多隻須要兩次硬盤的讀取。而若是使用二叉樹,那就不得了了,光是樹的高度就不知道比使用 B 大到哪裏去,對硬盤的讀取次數天然也多得多。
B 樹仍是有缺陷的,若是咱們要遍歷一顆 B 樹,必須往返於每一個結點之間,也就意味着得屢次訪問硬盤,有沒有可能讓遍歷時每一個元素只訪問一次呢?咱們在原有的 B 樹結構基礎上,加上新的元素組織形式,這就是 B+ 樹。
B+ 樹與 B 樹的差別在於:
B+ 全部關鍵字數據地址都存在葉子節點上,因此每次查找的次數都相同,查詢效率也比 B 樹穩定。B+ 樹也結點遍歷速度更快,由於只須要從最左側的葉子結點出發,一直沿着指向下一葉子結點的指針遍歷便可。另外,B+ 樹自然具有排序功能,所以特別適合帶有範圍的查找。