關於B樹的一點理解

2021-09-01 21:07:05 字數 3941 閱讀 1207

首先,需要強調的是b樹對應的英文名字就是b-tree(名字中的-其實是連字元),並沒有一種b減樹。b樹種的英文本母b是balance的意思。也就是說b樹是自平衡樹

目前有許多不同的技術可用來在計算機系統中提供儲存能力。例如,矽制的儲存晶元,速度比較快,但是卻造價相對昂貴,且失電後儲存內容丟失;磁儲存技術造價相對比較低,失電後不會丟失儲存內容,但是卻速度慢。為了在容量,速度及成本三者上取得乙個平衡,目前大多數的計算機都採用了多級儲存體系。即使用矽制的儲存晶元作為主存,使用磁儲存技術作為輔存,且通常輔存比主存的容量大至少兩個數量級。

下圖是乙個典型的磁碟驅動器。

了解磁碟驅動器大概的造型後,讓我們來看看磁碟驅動器的結構。

從磁碟驅動器結構圖中可以看出,驅動器包含若干碟片,他們以固定速度共用的主軸旋轉。每個盤的表面覆蓋一層可磁化的物質。每個磁碟通過磁臂末端的磁頭來讀寫。磁臂是物理連線在一起的,它們可以將磁頭移近或者遠離主軸。當乙個給定的磁頭靜止時,由它底下經過的盤表面成為乙個磁軌。讀/寫磁頭始終是垂直對齊的,因此它們下面的一組磁軌被同時訪問,這些被同時訪問的磁軌稱作柱面。

因為磁碟驅動器有機械移動的部分:盤旋轉和磁臂移動。因此相對主存來說磁碟的速度很慢。目前商用的磁碟以每分鐘5400~15000轉(rpm,round per minute)的速度旋轉,而7200rpm是最常見的。雖然7200rpm看起來很快,但是旋轉一周要花8.3毫秒,比矽儲存的常見訪問時間100納秒幾乎大5個數量級。換句話說,如果要等候乙個磁碟轉完完整的一圈,讓乙個特定的資料項到達讀/寫磁頭下方,我們在這個時間可以訪問主存幾乎100000次!平均來講只需要等候半圈,但是矽儲存體與磁碟的訪問時間之間的差異仍然是巨大的。而且移動磁臂也需要花費一些時間。另外通常資訊會被分割成一些在柱面內連續出現的大小相等的位的頁面,每次磁碟讀寫的都是乙個或者多個完整的頁面。

磁碟上資料必須用乙個三維位址唯一標示:柱面號、盤面號、塊號(磁軌上的盤塊)

讀/寫磁碟上某一指定資料需要下面3個步驟:

1.首先根據柱面號移動磁臂使磁頭移動到所需要的柱面上,這一過程被稱為定位或者查詢。

2.根據盤面號來確定指定盤面上的磁軌。

3.盤面確定之後,碟片開始旋轉,講指定的塊號的磁軌段移動至磁頭下。

經過上面三個步驟,指定資料的儲存位置就被找到。這時就可以開始讀/寫操作了。

訪問某一具體資訊,由3部分時間組成:

根據上述分析我們可以知道:

總的來說,磁碟訪問的次數是按需要從磁碟中讀出或者向磁碟中寫入的資訊的頁數來度量的。因此可以使用我們將要讀/寫的頁面數來作為訪問磁碟的總時間的近視值。也就是讀取的頁面數越少總時間也就越少。

基於往磁碟中訪問的頁面數越少總時間越少,且磁碟的訪問時間遠比主存耗時大的情況,科學家們設計了一種「又胖又矮」的平衡查詢樹——b樹。

常見的b樹定義有基於度數和基於階數兩種,我們先來看看《演算法導論》中基於度數的b樹定義:

一顆b樹t是具有如下性質的有根樹(根為root[t]):

每個結點x有以下域:

a. n[x],當前儲存在結點x中的關鍵字數,

b. n[x]個關鍵字本身,以非降序存放,因此key1[x]<=key2[x]<=…<=keyn[x][x],

c. leaf[x],是乙個布林值,如果x是葉子節點的話,則它為true,如果x為乙個內結點,則為false。

每個內結點x還包含n[x]+1個指向其子女的指標c1[x],c2[x], … ,cn[x]+1[x].葉子節點沒有子女,所以他們的ci域無定義。

各關鍵字keyi[x]對儲存在各子樹中的關鍵字範圍加以分隔:如果ki為儲存在以ci[x]為根的子樹中的關鍵字,則key1

\leq

≤key1[x]≤

\leq

≤k2≤

\leq

≤key2[x]≤

\leq

≤…≤\leq

≤keyn[x][x]≤

\leq

≤kn[x]+1

每個葉子節點具有相同的深度,即樹的高度h。

每個節點能包含的關鍵字數有乙個上界和下界,這些界可用於乙個稱為b樹的最小度數的固定整數t$\geq$2來表示。

a. 每個非根的結點必須至少有t-1個關鍵字。每個非根的內結點至少有t個子女。如果樹是飛空的,則根結點至少包含乙個關鍵字。

b. 每個結點可包含至多2t-1個關鍵字。所以乙個內結點至多可有2t個子女。如果乙個結點它恰好有2t-1個關鍵字,我們就說乙個結點是滿的。

從上面的描述來看,每個結點包含的關鍵字數t-1≤

\leq

≤n[x] ≤

\leq

≤ 2t-1,也就是⌈t/2⌉ ≤

\leq

≤n[x]/2≤

\leq

≤⌊t-1/2⌋ =t-1,即b樹結點要求關鍵字半滿。

現在我們來看看wiki中基於階數的定義:

乙個 m 階的b樹是乙個有以下屬性的樹:

每乙個節點最多有 m 個子節點。

每乙個非葉子節點(除根節點)最少有 ⌈m/2⌉ 個子節點。

如果根節點不是葉子節點,那麼它至少有兩個子節點。

有 k 個子節點的非葉子節點擁有 k − 1 個鍵。

所有的葉子節點都在同一層。

每乙個內部節點的鍵將節點的子樹分開。例如,如果乙個內部節點有3個子節點(子樹),那麼它就必須有兩個鍵: a1 和 a2 。左邊子樹的所有值都必須小於 a1 ,中間子樹的所有值都必須在 a1 和a2 之間,右邊子樹的所有值都必須大於 a2 。

也就是結點包含的關鍵字數⌈m/2⌉≤

\leq

≤n[x]≤

\leq

≤m-1。

根據如上所述,其實t度的b數就是2t階的b數,因為t度的b數結點最多有2t個孩子,2t-1個關鍵字,m階的b樹最多有m個孩子,區別就是乙個使用這個b樹節點的最小度數乙個是用的這個樹節點的最大度數。

如下圖所示是乙個典型的b樹結構:

為了減少讀寫磁碟的次數,通常b樹的每個結點都是磁碟乙個頁面的大小。

以上圖b樹結構為例,假如我們需要查詢數值5:

第一次磁碟i/o:

首先載入根節點所在的磁碟頁面到記憶體中,然後在記憶體中進行比對,發現要查詢的數值少於9,因此繼續在b樹的左子樹中進行查詢。

載入2,6結點到記憶體中,和要查詢的數值5進行比較,發現5的數值位於該結點2,6之間,因此繼續在2,6之間子節點中搜尋。

載入3,5所在結點到記憶體中,和要查詢的數值5進行比較,最終在該結點中找到。

經過如上所述,可以發現其實b樹比較次數其實不必紅黑樹少,尤其是單一結點中元素數量很多時。但是由於磁碟的io速度很慢,記憶體中的比較耗時幾乎可以忽略不算。所以只要樹的高度足夠低,io次數足夠少,就可以提公升查詢效能。

由於b樹的結點中是有和關鍵字相聯絡的「附屬資料」的,因此每個b樹的結點中存放的關鍵字相對來說沒有那麼多。同時也應為這個特性導致b樹的查詢效能不穩定。

在b樹種進行範圍查詢時,需要進行中序遍歷,操作有些麻煩。

b樹的這些缺點導致了b+樹的出現。

參考:演算法導論

b-tree wiki

漫畫演算法:什麼是b+樹

漫畫演算法:什麼是b樹

關於malloc的一點理解

在函式中使用malloc,如果是大的記憶體分配,而且malloc與free的次數也不是特別頻繁,使用malloc與free是比較合適的,但是如果記憶體分配比較小,而且次數特別頻繁,那麼使用malloc與free就有些不太合適了。因為過多的malloc與free容易造成記憶體碎片,致使可使用的堆記憶體...

關於HTTPS的一點理解

通訊使用明文 不加密 內容可能會被竊聽。不驗證通訊方的身份,因此有可能遭遇偽裝。無法證明報文的完整性,所以有可能已經遭到篡改。https http 認證 加密 完整性保護 https是與ssl 安全套接層 組合使用的http協議 http secure 使用ssl之後,請求則變成先和ssl通訊,ss...

關於Action的一點理解

之前學習jsp,就是從網上找些jsp例項 然後模仿,再加工成自己想要的,這樣一來,好多東西都是學了一點皮毛,例如action。下面是在看書時所知道的,看完後,有種頓悟的感覺。action的主要功能是生成頁面顯示所需要的資料,頁面則負責顯示action中的所設定的資料。頁面中的標籤在獲得action所...