爲什麼MySQL數據庫要用B+樹存儲索引

二叉樹,平衡二叉樹,紅黑樹,B樹,B+樹理解

 

數據庫中的數據一般是放在磁盤裏面,存取數據的時候就要訪問磁盤,
物理訪問過程:盤片旋轉,磁臂移動 兩個過程。盤片旋轉到指定位置之後,移動磁臂開始進行數據的存取。

那麼存取數據的時間(快慢)主要是在哪部分消耗呢?主要就是定位過程消耗的。
所以:考慮到提高存取數據的速率,實際上就是減少磁盤定位(I/O操作)的次數。

來舉個例子。來順序查找


查找5的時候,從頭到尾的遍歷,一共需要定位5次。不用再贅述,顯然這樣的順序查找是最低效的。

爲了提高效率,來二叉樹
二叉樹的規範我就不說了,

 

一共6個數,無論查找哪個數,最多也就定位3次。
嗯,既然二叉樹這麼方便,那大家都用二叉樹好了。額,其實圖一那種情況,也算是二叉樹,那算是一種情況。如果無法保證提高效率的穩定性,那這種結構還是不好。
(在這裏記錄一個知識點)
先序,中序,後序遍歷。說一點就好,這裏的先中後,說的是根節點。

爲了提升穩定性,來平衡二叉樹
平衡二叉樹用平衡因子差值來判斷是否平衡,並旋轉二叉樹。平衡因子:左右子樹高度差。平衡二叉樹裏平衡因子不能超過1,否則旋轉。
長嘆一口氣,這樣穩定了吧?
穩定是穩定,但是爲了二叉樹的穩定,犧牲了一些更重要的東西——時間。
當新增刪除數據導致的旋轉二叉樹時,很耗時間的!
所有的操作的目的都是爲了節省時間,提高效率。這樣操作捨本逐末了。但也不是絲毫沒有可取之處。
使用場景:新增刪除數據少,查找數據多的應用場景可以。

在穩定性的基礎上,再優化一下,減少一下旋轉次數吧,來紅黑樹
紅黑樹(Java中TreeMap)特性:
1、每個節點要麼是紅色,要麼是黑色。
2、根節點必須是黑色。
3、紅色節點不能連續(也即是,紅色節點的孩子和父親都不能是紅色)。
4、對於每個節點,從該點至null(樹尾端)的任何路徑,都含有相同個數的黑色節點。

 

紅黑樹旋轉的關鍵邏輯是:確保任何一個節點的左右子樹的高度差不會超過二者中較低那個的一倍。舉例:節點A,左子樹高度X,右子樹高度Y, X-Y<=min(X,Y);
所以當 X-Y > min(X,Y),然後開始旋轉,紅黑樹的旋轉邏輯請看這位大神博客。https://www.cnblogs.com/CarpenterLee/p/5503882.html ,很清晰了。

紅黑樹已經穩成這樣了,滿足嗎?不滿足,還可以更穩。來B樹
學習B樹的時候我曾看到這樣的定義。

子女?元素?孩子?值域?關鍵字?兒子?
OMG,雖然最後我理解了博主們的意思,但是這也太費勁兒了。所以按自己的理解,寫一個試試看。

前提:M階B樹
三種結點:根結點,中間結點,葉子結點
孩子:指一個結點下的子結點
關鍵字:結點中的值

1、根結點孩子數量:[2,M]
2、中間結點孩子數量:[ceil(M/2), M]
3、根結點和中間結點的關鍵字數量:他們的孩子數量 -1

4、一個結點當中:指向孩子指針和關鍵字的位置關係是:(指針1) 關鍵字A (指針2) 關鍵字B (指針3)
   每個關鍵字的值 > 左指針 指向的孩子樹裏結點中的關鍵字
   每個關鍵字的值 < 右指針 指向的孩子樹裏結點中的關鍵字

5、葉子結點位於同一層
6、結點中的關鍵字從小到大排列
7、結點中關鍵字不重複

 


圖片和定義都祭出之後,B樹對於紅黑樹的優勢很明顯了,最明顯的就是B樹一個結點存放了多個關鍵字。將在磁盤中的定位操作移到了結點中的關鍵字大小比較

 

B樹是很可以,但並不是對所有場景都友好。來B+樹
先說說什麼場景B樹不友好,範圍查詢:比如要找上圖中E->O,兩個字母之間的所有字母。那B樹的邏輯就是中序查找到E,繼續中序查找到O,然後拿出來字母。
那麼B+樹對於這種場景就很簡單了。來先說一說B+樹基本的東西,說完也就知道了爲什麼用B+樹範圍查找比B樹簡單了。

1、根節點和中間結點 的 孩子數量 = 關鍵字數量
2、根節點和中間結點 的 關鍵字 是 關鍵字對應子樹中所有關鍵字的最大值,同時也存在於子樹中
3、根節點和中間結點 只做索引,不包含數據指針以及數據

4、葉子結點包含所有數據,並按照從小到大順序排列
5、葉子結點用指針連在一起

所以,對於範圍查詢:比如查找3-8之間的數字,B+樹的做法是直接在葉子結點上的有序鏈表上遍歷即可。
而且,B+樹比B樹的查找更加穩定,因爲每次找到都會到葉子結點。
那爲什麼B+樹每次都會到葉子結點?B樹每次到哪裏?
B樹上的關鍵字代表一個索引key,和它同時存在的是key所指向的內容在內存中實際的存儲位置。如果遍歷到了某個關鍵字,那麼就根據指針去真實數據的存儲位置。
B+樹上的 非葉子節點 關鍵字只代表索引key,葉子結點上存儲真實數據 或者 指向真實數據位置 的指針。

二叉樹是一種樹形結構:

特點是與每個節點關聯的子節點至多有兩個(可爲0,1,2

每個節點的子節點有關聯位置關係

定義:

二叉樹是節點的有限集合,該集合或爲空集,或由一個根元素和兩棵不相交的二叉樹組成(遞歸定義)

二叉樹的兩棵子樹分別稱爲它的左子樹和右子樹

 

二叉樹的5種基本形態:

 

空二叉樹

只有根節點

只有左子樹,右子樹爲空

只有右子樹,左子樹爲空

左右子樹都不爲空

 

 

滿的和完全的二叉樹:

滿二叉樹:樹中每個分支節點(非葉節點)都有兩棵非空子樹

完全二叉樹:除最下兩層外,其餘節點度數都是2,如果最下面的節點不滿,則所有空位都在右邊,左邊沒有空位,如下圖

 

 

 

擴充二叉樹(由已有非空二叉樹生成的一種二叉樹):

是原二叉樹的最小節點擴充,使原樹中所有節點的度數都變成2

 

二叉樹的性質:

性質1. 非空二叉樹第 i 層上至多有 2i 個結點(i ≥ 0

性質2. 高度爲 k 的二叉樹至多有 2k-1 個結點(k ≥ 0)

性質3. 對任何非空二叉樹 T,若其葉結點個數爲 n0,度數爲 2 的結點

個數爲 n2,則n0 = n2 + 1

性質4. n 個結點的完全二叉樹的高度 k = ⎡log2(n+1)⎤

性質5. 滿二叉樹裏的葉結點比分支結點多一個

二叉樹的數據結構

基本操作

創建二叉樹

一棵二叉樹或爲空(用 None 表示),或是兩棵已有二叉樹和要存在樹根結點的一項數據,構造起的根結點代表構造出的二叉樹:

BiTree(dat, left, right)

判斷樹空:is_empty(bitree)

訪問操作,訪問二叉樹的組成成分:

訪問二叉樹的根結點數據元素:data()

取得一棵二叉樹的左右子樹:right(),left()

 

 

case ... esac 與其他語言中的 switch ... case 語句類似,是一種多分枝選擇結構。

 

case 語句匹配一個值或一個模式,如果匹配成功,執行相匹配的命令。case語句格式如下:

 

​   case工作方式如上所示。取值後面必須爲關鍵字 in,每一模式必須以右括號結束。取值可以爲變量或常數。匹配發現取值符合某一模式後,其間所有命令開始執行直至 ;;。;; 與其他語言中的 break 類似,意思是跳到整個 case 語句的最後。

 

​   取值將檢測匹配的每一個模式。一旦模式匹配,則執行完匹配模式相應命令後不再繼續其他模式。如果無一匹配模式,使用星號 * 捕獲該值,再執行後面的命令

 

1. 樹

 

2. 紅黑樹

3. 紅黑樹。。。

4. 紅黑樹的定義和如何實現的就不要說了,說說紅黑樹的優點

5. 二叉排序樹【左邊比根節點小,後邊比根節點大】

6. 二叉排序樹的退化

 

 7. 紅黑樹

8.因爲:

 

 

 

 9.B樹

 

 

 

 

 

 10. 文件系統用B樹,不用紅黑樹或別的呢

 

 

 

 

 

 

 

 

 

 11. B+ 樹

 

 

 

 

如果是多條的話,B 樹需要做局部的中序遍歷,可能要跨層訪問。

而 B+ 樹由於所有數據都在葉子結點,不用跨層,同時由於有鏈表結構,只需要找到首尾,通過鏈表就能把所有數據取出來了。

 

 

 


 

 

回到現場

 

HAHAHA

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章