面試官問你B樹和B+樹,就把這篇文章丟給他

原文連接:面試官問你B樹和B+樹,就把這篇文章丟給他html

1 B樹

在介紹B+樹以前, 先簡單的介紹一下B樹,這兩種數據結構既有類似之處,也有他們的區別,最後,咱們也會對比一下這兩種數據結構的區別。面試

1.1 B樹概念

B樹也稱B-樹,它是一顆多路平衡查找樹。二叉樹我想你們都不陌生,其實,B樹和後面講到的B+樹也是從最簡單的二叉樹變換而來的,並無什麼神祕的地方,下面咱們來看看B樹的定義。數據庫

  • 每一個節點最多有m-1個關鍵字(能夠存有的鍵值對)。
  • 根節點最少能夠只有1個關鍵字
  • 非根節點至少有m/2個關鍵字
  • 每一個節點中的關鍵字都按照從小到大的順序排列,每一個關鍵字的左子樹中的全部關鍵字都小於它,而右子樹中的全部關鍵字都大於它。
  • 全部葉子節點都位於同一層,或者說根節點到每一個葉子節點的長度都相同。
  • 每一個節點都存有索引和數據,也就是對應的key和value。

因此,根節點的關鍵字數量範圍:1 <= k="" <="m-1,非根節點的關鍵字數量範圍:m/2 <= k="" <="m-1。 數據結構

另外,咱們須要注意一個概念,描述一顆B樹時須要指定它的階數,階數表示了一個節點最多有多少個孩子節點,通常用字母m表示階數。性能

咱們再舉個例子來講明一下上面的概念,好比這裏有一個5階的B樹,根節點數量範圍:1 <= k="" <="4,非根節點數量範圍:2"> 3d

下面,咱們經過一個插入的例子,講解一下B樹的插入過程,接着,再講解一下刪除關鍵字的過程。指針

1.2 B樹插入

插入的時候,咱們須要記住一個規則:判斷當前結點key的個數是否小於等於m-1,若是知足,直接插入便可,若是不知足,將節點的中間的key將這個節點分爲左右兩部分,中間的節點放到父節點中便可。code

例子:在5階B樹中,結點最多有4個key,最少有2個key(注意:下面的節點統一用一個節點表示key和value)。cdn

  • 插入18,70,50,40

  • 插入22

插入22時,發現這個節點的關鍵字已經大於4了,因此須要進行分裂,分裂的規則在上面已經講了,分裂以後,以下。htm

  • 接着插入23,25,39

分裂,獲得下面的。

更過的插入的過程就很少介紹了,相信有這個例子你已經知道怎麼進行插入操做了。

1.3 B樹的刪除操做

B樹的刪除操做相對於插入操做是相對複雜一些的,可是,你知道記住幾種狀況,同樣能夠很輕鬆的掌握的。

  • 如今有一個初始狀態是下面這樣的B樹,而後進行刪除操做。

  • 刪除15,這種狀況是刪除葉子節點的元素,若是刪除以後,節點數仍是大於m/2,這種狀況只要直接刪除便可。

  • 接着,咱們把22刪除,這種狀況的規則:22是非葉子節點,對於非葉子節點的刪除,咱們須要用後繼key(元素)覆蓋要刪除的key,而後在後繼key所在的子支中刪除該後繼key。對於刪除22,須要將後繼元素24移到被刪除的22所在的節點。

此時發現26所在的節點只有一個元素,小於2個(m/2),這個節點不符合要求,這時候的規則(向兄弟節點借元素):若是刪除葉子節點,若是刪除元素後元素個數少於(m/2),而且它的兄弟節點的元素大於(m/2),也就是說兄弟節點的元素比最少值m/2還多,將先將父節點的元素移到該節點,而後將兄弟節點的元素再移動到父節點。這樣就知足要求了。

咱們看看操做過程就更加明白了。

  • 接着刪除28,刪除葉子節點,刪除後不知足要求,因此,咱們須要考慮向兄弟節點借元素,可是,兄弟節點也沒有多的節點(2個),借不了,怎麼辦呢?若是遇到這種狀況,首先,仍是將先將父節點的元素移到該節點,而後,將當前節點及它的兄弟節點中的key合併,造成一個新的節點

移動以後,跟兄弟節點合併。

刪除就只有上面的幾種狀況,根據不一樣的狀況進行刪除便可。

上面的這些介紹,相信對於B樹已經有必定的瞭解了,接下來的一部分,咱們接着講解B+樹,我相信加上B+樹的對比,就更加清晰明瞭了。

2 B+樹

2.1 B+樹概述

B+樹其實和B樹是很是類似的,咱們首先看看相同點

  • 根節點至少一個元素
  • 非根節點元素範圍:m/2 <= k="" <="m-1" li="">

不一樣點

  • B+樹有兩種類型的節點:內部結點(也稱索引結點)和葉子結點。內部節點就是非葉子節點,內部節點不存儲數據,只存儲索引,數據都存儲在葉子節點。
  • 內部結點中的key都按照從小到大的順序排列,對於內部結點中的一個key,左樹中的全部key都小於它,右子樹中的key都大於等於它。葉子結點中的記錄也按照key的大小排列。
  • 每一個葉子結點都存有相鄰葉子結點的指針,葉子結點自己依關鍵字的大小自小而大順序連接。
  • 父節點存有右孩子的第一個元素的索引。

下面咱們看一個B+樹的例子,感覺感覺它吧!

2.2 插入操做

對於插入操做很簡單,只須要記住一個技巧便可:當節點元素數量大於m-1的時候,按中間元素分裂成左右兩部分,中間元素分裂到父節點當作索引存儲,可是,自己中間元素仍是分裂右邊這一部分的

下面以一顆5階B+樹的插入過程爲例,5階B+樹的節點最少2個元素,最多4個元素。

  • 插入5,10,15,20

  • 插入25,此時元素數量大於4個了,分裂

  • 接着插入26,30,繼續分裂

有了這幾個例子,相信插入操做沒什麼問題了,下面接着看看刪除操做。

2.3 刪除操做

對於刪除操做是比B樹簡單一些的,由於葉子節點有指針的存在,向兄弟節點借元素時,不須要經過父節點了,而是能夠直接經過兄弟節移動便可(前提是兄弟節點的元素大於m/2),而後更新父節點的索引;若是兄弟節點的元素不大於m/2(兄弟節點也沒有多餘的元素),則將當前節點和兄弟節點合併,而且刪除父節點中的key,下面咱們看看具體的實例。

  • 初始狀態

  • 刪除10,刪除後,不知足要求,發現左邊兄弟節點有多餘的元素,因此去借元素,最後,修改父節點索引

  • 刪除元素5,發現不知足要求,而且發現左右兄弟節點都沒有多餘的元素,因此,能夠選擇和兄弟節點合併,最後修改父節點索引

  • 發現父節點索引也不知足條件,因此,須要作跟上面一步同樣的操做

這樣,B+樹的刪除操做也就完成了,是否是看完以後,以爲很是簡單!

3 B樹和B+樹總結

B+樹相對於B樹有一些本身的優點,能夠歸結爲下面幾點。

  • 單一節點存儲的元素更多,使得查詢的IO次數更少,因此也就使得它更適合作爲數據庫MySQL的底層數據結構了。
  • 全部的查詢都要查找到葉子節點,查詢性能是穩定的,而B樹,每一個節點均可以查找到數據,因此不穩定。
  • 全部的葉子節點造成了一個有序鏈表,更加便於查找。
相關文章
相關標籤/搜索