資料結構與演算法問題,困擾了無數的小夥伴。
很多小夥伴對資料結構與演算法的認知有一個誤區,認為工作中沒有用到,為什麼面試要問,問了能解決實際問題?
圖靈獎獲得者: Niklaus Wirth 說過: 程式=資料結構+演算法, 也就說我們無時無刻都在和資料結構打交道。
只是作為Java開發,由於技術體系的成熟度較高,使得大部分人認為:程式應該等於 框架 + SQL 呀?
今天我們就來分析一道資料結構的題目:”B樹和B+樹“。
關於這個問題,我們來看看普通人和高手的回答!
普通人:
嗯. 我想想 … 嗯… Mysql裡面好像是用了B+樹來做索引的! 然後…
高手:
為了更清晰的解答這個問題,我打算從三個方面來回答:
- 瞭解二叉樹、AVL樹、B樹的概念
- B樹和B+樹的應用場景
- B樹是一種多路平衡查詢樹,為了更形象的理解。
二叉樹,每個節點支援兩個分支的樹結構,相比於單向連結串列,多了一個分支。
二叉查詢樹,在二叉樹的基礎上增加了一個規則,左子樹的所有節點的值都小於它的根節點,右子樹的所有子節點都大於它的根節點。
二叉查詢樹會出現斜樹問題,導致時間複雜度增加,因此又引入了一種平衡二叉樹,它具有二叉查詢樹的所有特點,同時增加了一個規則:”它的左右兩個子樹的高度差的絕對值不超過1“。平衡二叉樹會採用左旋、右旋的方式來實現平衡。
而B樹是一種多路平衡查詢樹,它滿足平衡二叉樹的規則,但是它可以有多個子樹,子樹的數量取決於關鍵字的數量,比如這個圖中根節點有兩個關鍵字3和5,那麼它能夠擁有的子路數量=關鍵字數+1。
因此從這個特徵來看,在儲存同樣資料量的情況下,平衡二叉樹的高度要大於B樹。
B+樹,其實是在B樹的基礎上做的增強,最大的區別有兩個:
-
- B樹的資料儲存在每個節點上,而B+樹中的資料是儲存在葉子節點,並且通過連結串列的方式把葉子節點中的資料進行連線。
- B+樹的子路數量等於關鍵字數
這個是B樹的儲存結構,從B樹上可以看到每個節點會儲存資料。
這個是B+樹,B+樹的所有資料是儲存在葉子節點,並且葉子節點的資料是用雙向連結串列關聯的。
2.B樹和B+樹,一般都是應用在檔案系統和資料庫系統中,用來減少磁碟IO帶來的效能損耗。
以Mysql中的InnoDB為例,當我們通過select語句去查詢一條資料時,InnoDB需要從磁碟上去讀取資料,這個過程會涉及到磁碟IO以及磁碟的隨機IO
我們知道磁碟IO的效能是特別低的,特別是隨機磁碟IO。
因為,磁碟IO的工作原理是,首先系統會把資料邏輯地址傳給磁碟,磁碟控制電路按照定址邏輯把邏輯地址翻譯成實體地址,也就是確定要讀取的資料在哪個磁軌,哪個扇區。
為了讀取這個扇區的資料,需要把磁頭放在這個扇區的上面,為了實現這一個點,磁碟會不斷旋轉,把目標扇區旋轉到磁頭下面,使得磁頭找到對應的磁軌,這裡涉及到尋道事件以及旋轉時間。
很明顯,磁碟IO這個過程的效能開銷是非常大的,特別是查詢的資料量比較多的情況下。
所以在InnoDB中,乾脆對儲存在磁碟塊上的資料建立一個索引,然後把索引資料以及索引列對應的磁碟地址,以B+樹的方式來儲存。
如圖所示,當我們需要查詢目標資料的時候,根據索引從B+樹中查詢目標資料即可,由於B+樹分路較多,所以只需要較少次數的磁碟IO就能查詢到。
3.為什麼用B樹或者B+樹來做索引結構?原因是AVL樹的高度要比B樹的高度要高,而高度就意味著磁碟IO的數量。所以為了減少磁碟IO的次數,檔案系統或者資料庫才會採用B樹或者B+樹。
以上就是我對B樹和B+樹的理解!
總結
資料結構在實際開發中非常常見,比如陣列、連結串列、雙向連結串列、紅黑樹、跳躍表、B樹、B+樹、佇列等。
在我看來,資料結構是程式設計中最重要的基本功之一。
學了順序表和連結串列,我們就能知道查詢操作比較多的場景中應該用順序表,修改操作比較多的場景應該使用連結串列。
學了佇列之後,就知道對於FIFO的場景中,應該使用佇列。
學了樹的結構後,會發現原來查詢類的場景,還可以更進一步提升查詢效能。
基本功決定大家在技術這個崗位上能夠走到的高度。
好的,本期的普通人VS高手面試系列就到這裡結束了,喜歡的朋友記得點贊收藏。
如果最近大家遇到一些場景類和方案設計類的問題,歡迎私信我,我在後續的內容中給大家做解答!
部分高手面試文件已整理,需要的小夥伴可以私信或者評論區留言。