樹 - (二叉查找樹,紅黑樹,B樹)- B樹

雖是讀書筆記,可是如轉載請註明出處 http://segmentfault.com/blog/exploring/
.. 拒絕伸手複製黨html

如下是算法導論第十八章的學習筆記算法


一個問題

若是紅黑樹中的每一個黑結點吸取它的紅子女,並把它們的子女併入自身,描述這個結果的數據結構。
(2-3-4樹)
or
假設將一棵紅黑樹的每個紅結點 「吸取」 到它的黑色父結點中,來讓紅結點的子女變成黑色父結點的子女(忽略關鍵字的變化)。當一個黑結點的全部紅色子女都被吸取後,其可能的度是多少?此結果樹的葉子深度怎樣segmentfault

B樹 - 平衡多路查找樹

圖片描述

這段整理自July's blog 和 本身的理解
磁盤讀取數據(把數據從外存調入內存)是以盤塊(block)爲基本單位的。位於同一盤塊中的全部數據都能被一次性所有讀取出來。而磁盤IO代價主要花費在查找時間上。所以咱們應該儘可能將相關信息存放在同一盤塊,同一磁道中,這樣一次IO時間就能夠。或者至少放在同一柱面或相鄰柱面上,以求在讀/寫信息時儘可能減小磁頭來回移動的次數,避免過多的查找時間。數據結構

因此,在大規模數據存儲方面,大量數據存儲在外存磁盤中,而在外存磁盤中讀取/寫入塊(block)中某數據時,首先須要定位到磁盤中的某塊,如何有效地查找磁盤中的數據,須要一種合理高效的外存數據結構,B 樹是爲了磁盤或其它存儲設備而設計的一種多叉平衡查找樹。函數

與紅黑樹不一樣之處在於,B樹的節點能夠有許多個,從幾個到幾千個。不過 B 樹與紅黑樹同樣,一棵含 n 個結點的 B 樹的高度也爲 O(logn) ,但可能比一棵紅黑樹的高度小許多,由於對數的底由紅黑樹的2變爲t(t爲最小度數). 由於它的分支因子比較大。因此,B 樹能夠在 O(logn)時間內,實現各類如插入(insert),刪除(delete)等動態集合操做。學習

B樹的每一個節點根據實際狀況能夠包括大量信息和子女(固然是不能超過磁盤塊的大小,由於咱們從磁盤上讀取信息的時候通常都是按照磁盤塊進行的,一個磁盤快對應一個節點,每次檢索B樹的時候遇到一個節點,也就對應一次磁盤的訪問操做,若是一個節點大於了一個磁盤塊,那麼訪問一個節點須要兩次磁盤訪問,效率就不行了,通常塊的大小在 1k~4k 左右 )spa

clipboard.png
如圖 17是磁盤文件名;小紅方塊表示這個 17 文件內容在硬盤中的存儲位置;p1 表示指向 17 左子樹的指針設計


B樹性質

若是是一棵 m 階的 B 樹,那麼有:指針

  • m階樹的孩子數
    $$ ceil( \frac{m}{2} ) \leq 孩子數 \leq m $$
  • 除根結點和葉子結點外,其它每一個結點至少有 ceil(m / 2) 個孩子(其中 ceil(x) 是一個取上限的函數);
  • 除根結點以外的結點的關鍵字的個數 n 必須知足:
    $$ ceil(\frac{m}{2})-1 \leq n \leq m-1 $$(葉子結點也必須知足此條關於關鍵字數的性質)
  • 樹的高度
    $$ h = \log_{t}{(\frac{n+1}{2} + 1)} $$
    $$ t = ceil( \frac{m}{2} )$$

節點

B 樹的類型和節點定義以下圖所示:
圖片描述code

查找操做

假如每一個盤塊能夠正好存放一個 B 樹的結點(正好存放 2 個文件名)。那麼一個 BTNODE 結點就表明一個盤塊,而子樹指針就是存放另一個盤塊的地址。

下面,我們來模擬下查找文件 29 的過程:(詳細見July博客)

  • 根據根結點指針找到文件目錄的根磁盤塊 1,將其中的信息導入內存。【磁盤 IO 操做 1 次】
  • 此時內存中有兩個文件名 1七、35 和三個存儲其餘磁盤頁面地址的數據。根據算法咱們發現:17<29<35,所以咱們找到指針 p2。
  • 根據 p2 指針,咱們定位到磁盤塊 3,並將其中的信息導入內存。【磁盤 IO 操做 2 次】
  • 此時內存中有兩個文件名 26,30 和三個存儲其餘磁盤頁面地址的數據。根據算法咱們發現:26<29<30,所以咱們找到指針 p2。
  • 根據 p2 指針,咱們定位到磁盤塊 8,並將其中的信息導入內存。【磁盤 IO 操做 3 次】
  • 此時內存中有兩個文件名 28,29。根據算法咱們查找到文件名 29,並定位了該文件內存的磁盤地址。

分析上面的過程,發現須要 3 次磁盤 IO 操做和 3 次內存查找 操做。關於內存中的文件名查找,因爲是一個有序表結構,能夠利用折半查找提升效率。至於 IO 操做是影響整個 B 樹查找效率的決定因素。

查詢須要O(h)存取的磁盤頁面數

插入操做

插入元素 - 檢查是否存在
- 存在,不插入
- 不存在,在葉子節點插入新的元素

  • 葉子節點空間足夠(#<m-1),插入

  • 葉子節點空間不夠(#=m-1),插入進去,而後分裂,中間節點上移

  • 若是致使父節點滿了,父節點再分裂;若致使根節點滿了。這樣致使樹的高度+1

刪除操做

高度爲h的樹,只須要O(h)次磁盤存取操做。

刪除元素 - 檢查BTree是否存在該節點
- 不存在,不刪除
- 存在,刪除之,而後判斷:該元素是否有左右孩子

  • 如有,則上移``孩子中相近元素 (「左孩子最右邊的節點」 或 「右孩子最左邊的節點」) 到該節點 - to step *

  • 若無,直接刪除 , - to step *

  • step *: 若是刪除以後或者移動以後,致使某節點的元素數目小於 ceil(m/2)-1;則須要查看某相鄰的兄弟節點是否豐滿 (大於 ceil(m/2)-1)

    step *1. 父節點降低一個關鍵字到該節點;降低
    --判斷兄弟 --
    step *2.1 若是其某個相鄰兄弟結點中比較豐滿(元素個數大於 ceil(m/2)-1),則能夠借給父結點一個元素,即將最豐滿的相鄰兄弟結點中上移到父節點中 上調
    step *2.2 若是其相鄰兄弟都剛脫貧,即借了以後其結點數目小於 ceil(m/2)-1,則該結點與其相鄰的某一兄弟結點進行 合併 成一個結點,以此來知足條件 合併

相關文章
相關標籤/搜索