1. 程式人生 > >B-Tree和B+Tree

B-Tree和B+Tree

結構 假設 所在 文章 分別是 是我 b樹 b- 過程

首先,介紹一下什麽是樹(tree)

  樹,就是一種順序。我們有從小到大,從大到小的順序,也自然會有“樹”這種順序。

  那麽,樹,是一個怎麽樣的順序呢?

對於一列數,只能保持兩種狀態:①無序②有序

   而這兩者最大的區別就是:查找的方式不同

 面對無序數列,我們只能依次比較,去尋找目標值。(順序查找)

 而對於有序數列,我們可以通過某種規矩去推演目標所在的位置。

  而“樹”,就是我們推理的規則。

一、二叉樹(有序二叉查找樹)

  規定:在一組數列中選擇一個值作為“根節點”,數列中剩下的值大於它的全部放在右側,小於它的值全部放在左邊,且所有節點最多有左右兩個子節點。  

    1、任意一個不為空的左子樹節點

,則左子樹的值均小於根節點的值;

    2、任意一個不為空的右子數節點,則右子樹的值均大於於根節點的值;

    3、任意節點的左右子樹也分別是二叉查找樹;

    4、沒有鍵值相等的節點;

  查詢方式:比較節點值和目標值,目標較大往右,較小則往左,等於則找到。

技術分享圖片

以圖中為例:

  我們想要查找“5”這個目標值,需要6→3→5三步。

  而如果是“3“、”7”這兩個目標值,就只需兩步。

  所以,平均下來就是(3+3+3+2+2+1)/6 = 2.3

然後,我們在跟無序數列的依次查找作比較:
  從最好到最壞情況:(1+2+3+4+5+6)/6 = 3.3

 很明顯,以“樹”這種順序查找,要比依次查找快好多。

但是,我們說這有一種局限性,就是如果根節點沒有選擇“6”,而是選擇了最小的“2”,那麽樹就會變成這樣:

  技術分享圖片

當樹變成這樣時,我們在來查找就會

  (1+2+3+4+5+5)/6 = 3.16

這與“順序查找”幾乎一樣,所以樹的建立異常重要。

二、AVL樹(平衡二叉樹——Balance Tree)

  在普通二叉樹的基礎上,AVL樹嚴格要求了: 

    所有節點的左右子樹高度差不超過1 

  也就是,剛開始演示的那棵“樹”。

  如果,左右子樹的高度超出了要求,那麽就要用到“旋轉”

旋轉重排序

  口訣:子、父換位,重新“認父”,葉子不動

    來看下圖理解:

技術分享圖片

上圖就是常說的LL型,但我個人覺得討論這些“型”沒有任何意義。

  第一步:找到哪兩個節點相差2,圖中為“3”與“9”;

  第二步:找到在“3”這條分支上與“9”同級的節點,圖中為“6”;

  第三步:將子節點與父節點換位,圖中為“6”與“8”

  第四步:將多出來的節點,按照二叉樹的規定重新分配,圖中為‘7’變更為“8”的子節點。

技術分享圖片

技術分享圖片

按照,此方不論是LR、RL、RR 都能夠輕易翻轉:
  如下圖的RL:

    技術分享圖片

很顯然,這種二叉樹一旦變動,就相當麻煩,所以人們就又發明了一個條件不那麽苛刻的樹。

 三、紅黑樹

  由於,它也是一種二叉樹,所以它在具備普通二叉樹的條件外,新增:
    1、每個結點要麽是紅的要麽是黑的
    2、根節點是黑色的
    3、每個葉節點(葉節點即樹尾端NIL指針或NULL結點)都是黑的
    4、如果一個結點時紅的,那麽它的兩個兒子都是黑的
    5、對於任意結點而言,其到葉節點樹尾端NIL指針的每條路徑都包含相同數目的黑結點。

為什麽,它能比AVL樹相對來說寬松一些呢?

  我說下,一個困擾我很久的問題:就是"紅"、“黑”到底代表什麽?

    這個其實很簡單,就是將數列分成兩組數來保持平衡紅、黑只是記號,你要想叫“藍”、“白”樹也隨你。

    那怎麽來保持平衡呢?這種平衡怎麽就比AVL松了呢?  

  我們,先拋開“樹”不談,我們先講一個小學知識—間隔插入

      規定:公路上種了5棵樹,頭尾不能站人,人後面必須跟著一棵樹,兩樹之間可以不站人。

        問,這5棵樹中最少、最多能站多少人?

      這不很簡單嗎,最少 = 0人 , 最多 = (5-1)4人

  那麽,在“紅黑樹”的概念上,0人平衡於4人。這就比AVL寬松多了。

關於,紅黑樹的插入、刪除會有專門一篇來分析。

四、B-Tree(Branches Tree 多路查找樹)

  首先,強調一些“術語”:“高度”——從葉節點到目標節點的長度、“深度”——從根節點到目標節點的長度、“階數”——節點的最大兒子(分支)個數

    網上找的例子:

技術分享圖片

拿"G"節點舉例,設根、葉節點深、高度為 0 ,“G”的深度 =2、高度 = 2、該樹階數 = 3.

所以,規定B-Tree 需滿足:

  1.一個M階的B-樹,每個非葉子節點最多只有M個兒子

  2、根結點的兒子數為[2, M]

  3、除根結點以外的非葉子結點的兒子數為[M/2, M]

  4、每個結點存放至少M/2-1(取上整)和至多M-1個關鍵字;(至少2個關鍵字)

  5、非葉子結點的關鍵字個數=指向兒子的指針個數-1

  6、非葉子結點的關鍵字:K[1], K[2], …, K[M-1];且K[i] < K[i+1]

  7、非葉子結點的指針:P[1], P[2], …, P[M];其中P[1]指向關鍵字小於K[1]的子樹,P[M]指向關鍵字大於K[M-1]的子樹,其它P[i]指向關鍵字屬於(K[i-1], K[i])的子樹;

  8所有葉子結點位於同一層

 由於,B-Tree的關鍵字不再像二叉樹那樣內個節點只有一個,那麽我們就不能簡單的:大於往右,小於往左了。

  假設,一個節點中有 5 | 7 | 10 這三個關鍵字,那麽就是:大於10的向“最右”,大於7小於10的向“次右” ......等於關鍵字就取到,以此類推。

  網上找的圖片:

  技術分享圖片

下面來看下,B-Tree的插入刪除

  插入:

  技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

刪除:

  技術分享圖片

技術分享圖片

技術分享圖片

B+樹

為什麽要B+樹

由於B+樹的數據都存儲在葉子結點中,分支結點均為索引,方便掃庫,只需要掃一遍葉子結點即可,但是B樹因為其分支結點同樣存儲著數據,我們要找到具體的數據,需要進行一次中序遍歷按序來掃,所以B+樹更加適合在區間查詢的情況,所以通常B+樹用於數據庫索引,而B樹則常用於文件索引。

簡介

同樣的,以一個m階樹為例:

  1. 根結點只有一個,分支數量範圍為[2,m];
  2. 分支結點,每個結點包含分支數範圍為[ceil(m/2), m];
  3. 分支結點的關鍵字數量等於其子分支的數量減一,關鍵字的數量範圍為[ceil(m/2)-1, m-1],關鍵字順序遞增;
  4. 所有葉子結點都在同一層;

操作

其操作和B樹的操作是類似的,不過需要註意的是,在增加值的時候,如果存在滿員的情況,將選擇結點中的值作為新的索引,還有在刪除值的時候,索引中的關鍵字並不會刪除,也不會存在父親結點的關鍵字下沈的情況,因為那只是索引。

B樹和B+樹的區別

這都是由於B+樹和B具有這不同的存儲結構所造成的區別,以一個m階樹為例。

  1. 關鍵字的數量不同;B+樹中分支結點有m個關鍵字,其葉子結點也有m個,其關鍵字只是起到了一個索引的作用,但是B樹雖然也有m個子結點,但是其只擁有m-1個關鍵字。
  2. 存儲的位置不同;B+樹中的數據都存儲在葉子結點上,也就是其所有葉子結點的數據組合起來就是完整的數據,但是B樹的數據存儲在每一個結點中,並不僅僅存儲在葉子結點上。
  3. 分支結點的構造不同;B+樹的分支結點僅僅存儲著關鍵字信息和兒子的指針(這裏的指針指的是磁盤塊的偏移量),也就是說內部結點僅僅包含著索引信息。
  4. 查詢不同;B樹在找到具體的數值以後,則結束,而B+樹則需要通過索引找到葉子結點中的數據才結束,也就是說B+樹的搜索過程中走了一條從根結點到葉子結點的路徑

文章參考:

 http://www.cnblogs.com/George1994/p/7008732.html

https://blog.csdn.net/wanghanlincsdn/article/details/61208273

B-Tree和B+Tree