內心有點B樹

引言

數據庫的增刪改查等操做是開發過程當中最爲常見也是尤其重要的,尤爲是如今大數據的興起,致使數據存儲量急劇增長,提高數據的操做效率就變得尤其關鍵。算法

大部分數據庫的索引都採用樹的結構存儲,這是由於樹的查詢效率相對較高,且保持有序。數據庫

對於二叉搜索樹的時間複雜度是O(logN),在算法以及邏輯上來分析,二叉搜索樹的查找速度以及數據比較次數都是較小的。性能

可是咱們不得不考慮一個新的問題。大數據

數據量是遠大於內存大小的,那咱們在查找數據時並不能將所有數據同時加載至內存。既然不能所有加載至內存中就只能逐步的去加載磁盤中某個頁,簡而言之就是逐一的去加載磁盤,加數據分塊的加載至內存進行查找與比較。設計

例如:在下圖所示的樹中查找10,樹中的每一個節點表明一個磁盤頁。每次訪問一個新節點表明一次磁盤IO。3d

經過查找過程能夠看出,磁盤IO次數與樹的高度相關,在最壞狀況下,磁盤IO次數等於樹的高度。因爲磁盤IO過程是相對耗時效率較低的,所以,在設計數據存儲結構時須要下降樹的高度,即將一棵「瘦高」的樹變得「矮胖」。指針

當數據數目相同,在保持有序前提下,下降樹高度,只需將節點中存儲的key值增長,即二叉搜索樹中每一個節點只有一個key,現將一個節點中存儲多個key,獲得的樹即爲B樹。blog

定義

B樹也稱B-樹,B-樹直接讀做B樹,不能由於有「-」號就讀做B減樹,它是一顆多路平衡查找樹。咱們描述一顆B樹時須要指定它的階數,階數表示了一個結點最多有多少個孩子結點,通常用字母m表示階數。當m取2時,就是咱們常見的二叉搜索樹,m爲3時是2-3樹。索引

一顆m階的B樹定義以下:內存

(1)每一個結點最多有m-1個關鍵字。
(2)根結點最少能夠只有1個關鍵字。
(3)非根結點至少有Math.ceil(m/2)-1個關鍵字。Math.ceil(m/2)含義是向上取整。例如Math.ceil(4.5) = 5。
(4)每一個結點中的關鍵字都按照從小到大的順序排列,每一個關鍵字的左子樹中的全部關鍵字都小於它,而右子樹中的全部關鍵字都大於它。
(5)全部葉子結點都位於同一層,或者說根結點到每一個葉子結點的長度都相同。

查找

B-樹的查找實際上是對二叉搜索樹查找的擴展, 與二叉搜索樹不一樣的地方是,B-樹中每一個節點有不止一棵子樹。在B-樹中查找某個結點時,須要先判斷要查找的結點在哪棵子樹上,而後在結點中逐個查找目標結點。B樹的查找過程相對簡單,與二叉搜索樹相似,所以再也不贅述。

插入

B樹的插入操做是指在樹種插入一條新記錄,即(key, value)的鍵值對。若是B樹中已存在須要插入的鍵值對,則用須要插入的value替換舊的value。若B樹不存在這個key,則必定是在葉子結點中進行插入操做。

插入流程

B樹的插入流程以下:
  (1)根據要插入的key的值,對B樹執行查找操做,查找到待插入數據的當前節點位置。
  (2)判斷當前結點key的個數是否小於等於m-1,若知足,則結束直接插入數據,不然,進行第(3)步。
  (3)以結點中間的key爲中心分裂成左右兩部分,而後將這個中間的key插入到父結點中,這個key的左子樹指向分裂後的左半部分,這個key的右子支指向分裂後的右半部分,而後將當前結點指向父結點,繼續進行第(3)步。

實例圖解

下面以5階B樹爲例,介紹B樹的插入操做,在5階B樹中,結點最多有4個key,最少有2個key。

插入圖解:
  1:插入38,此時爲空樹,直接插入,並做爲根節點。繼續插入2二、7六、40,符合情形(2),直接插入。繼續插入51,符合情形(3),執行分裂。

  2:按照相同的步驟繼續插入1三、21。插入39,符合情形(3),致使節點分裂。選擇中值22做爲父節點,並將22節點上移,與40節點進行合併。

  3:按照一樣的插入規則,繼續向樹中插入key爲30、2七、3三、3六、3五、3四、2四、29的數據。插入完成後,繼續插入key爲26的數據,插入以後須要執行節點分裂。

  4:將key爲27的數據節點上移至父節點,此時父節點已經有4個key,插入key27的數據後須要執行節點分裂。在插入key爲26的數據後,致使根節點發生分裂,樹的高度加1。

性能分析

B樹插入過程首先須要執行一次查找操做,B樹的查找操做的時間複雜度爲O(mlogmn)。其中m爲B樹的階數,n爲B樹中key的數目。在插入過程,最耗時的情形即爲:插入數據後致使根節點發生分裂,分裂節點的操做是常數級,分裂操做向上回溯的時間複雜度爲O(h)。所以,B樹的插入操做的時間複雜度近似於查找操做,即O(mlogmn)。

刪除

刪除流程

B樹的刪除流程以下:
  (1)若是當前須要刪除的key位於非葉子結點上,則用後繼key(這裏的後繼key均指後繼記錄的意思)覆蓋要刪除的key,而後在後繼key所在的子支中刪除該後繼key。此時後繼key必定位於葉子結點上,這個過程和二叉搜索樹刪除結點的方式相似。刪除這個記錄後執行第2步
  (2)該結點key個數大於等於Math.ceil(m/2)-1,結束刪除操做,不然執行第(3)步。
  (3)若是兄弟結點key個數大於Math.ceil(m/2)-1,則父結點中的key下移到該結點,兄弟結點中的一個key上移,刪除操做結束。不然,將父結點中的key下移與當前結點及它的兄弟結點中的key合併,造成一個新的結點。原父結點中的key的兩個孩子指針就變成了一個孩子指針,指向這個新結點。而後當前結點的指針指向父結點,重複第(2)步。

實例圖解

刪除圖解:
  1:首先刪除21,符合情形(2)直接刪除。刪除21後,繼續刪除27,符合情形(1),使用後繼節點28替代27,並刪除28。

  2:刪除28後,當前節點只有一個key,所以須要按照情形(3)調整。當前節點的兄弟節點有3個key,父節點中key28下移,兄弟節點中key26上移,調整結束。調整完畢後繼續刪除32。

  3:刪除32後,須要按照情形(3)進行調整,當前節點的兄弟節點只有2個key,則將父節點下移,將當前節點與一個兄弟節點合併,調整完畢。繼續刪除39,刪除39後按照情形(3)進行調整。

  4:當前節點變爲只含有key40的節點,須要按照情形(3)繼續調整,執行節點的合併,合併操做中包含根節點,致使合併以後的樹的高度減1。

5.3 性能分析

B樹的刪除操做一樣須要執行查找過程,時間複雜度爲O(mlogmn)。刪除數據過程與插入過程相似,最壞狀況須要回溯O(h)。所以B樹的刪除操做的時間複雜度近似爲O(mlogmn)。

6 總結

B樹是一種平衡的多路查找樹。其設計思路主要是經過節點中存儲不止一個key,來下降樹的高度。同等比較次數下,樹的高度小保證磁盤IO次數相對較少,提升查找效率。

END

相關文章
相關標籤/搜索