b树与b+树的区别_面试必考:B树、B树、B+树、B*树图文详解
B樹(shù)
B樹(shù)又叫做二叉搜索樹(shù),倒?fàn)畹臉?shù)形結(jié)構(gòu)。如下圖所示
特點(diǎn):所有的非子夜節(jié)點(diǎn)最多擁有兩個(gè)子節(jié)點(diǎn)樹(shù)(左子樹(shù)和右子樹(shù))。
所有結(jié)點(diǎn)存儲(chǔ)一個(gè)關(guān)鍵字。
節(jié)點(diǎn)的左右兒子,左邊是比該節(jié)點(diǎn)小的,右邊是比該節(jié)點(diǎn)大的。
缺點(diǎn):
因?yàn)槎嫠阉鳂?shù)不存在平衡算法,所以在某些特殊的情況下,二叉搜索樹(shù)等同于線性,出現(xiàn)蹩腳的情況,設(shè)計(jì)者們發(fā)現(xiàn)降低樹(shù)的高度自然就可以提高查找效率。那么如何解決降低樹(shù)的高度的問(wèn)題?在這種基礎(chǔ)上設(shè)計(jì)者給二叉樹(shù)加入了平衡算法,出現(xiàn)了平衡樹(shù)。
二叉樹(shù)搜索樹(shù)的查詢?cè)?#xff0c;先從根節(jié)點(diǎn)開(kāi)始,和根節(jié)點(diǎn)匹配,若是比根節(jié)點(diǎn)小就進(jìn)入左子節(jié)點(diǎn),若是比根節(jié)點(diǎn)大進(jìn)行右子節(jié)點(diǎn),依次按照這樣的邏輯進(jìn)行,找到就返回。
另一方面樹(shù)的高度也會(huì)影響查詢的效率,設(shè)計(jì)者又是怎么解決的呢?
假設(shè)大規(guī)模數(shù)據(jù)存儲(chǔ)中,實(shí)現(xiàn)索引查詢這樣一個(gè)實(shí)際背景下,樹(shù)節(jié)點(diǎn)存儲(chǔ)的元素?cái)?shù)量是有限的,即使存儲(chǔ)在平衡二叉樹(shù)中,在大量數(shù)據(jù)的儲(chǔ)存情況下,這樣導(dǎo)致二叉平衡查找樹(shù)結(jié)構(gòu)由于樹(shù)的深度過(guò)大而造成磁盤(pán)I/O讀寫(xiě)過(guò)于頻繁,進(jìn)而導(dǎo)致查詢效率低下,那么如何減少樹(shù)的深度(當(dāng)然是不能減少查詢的數(shù)據(jù)量),一個(gè)基本的想法就是:采用多叉樹(shù)結(jié)構(gòu)(由于樹(shù)節(jié)點(diǎn)元素?cái)?shù)量是有限的,自然該節(jié)點(diǎn)的子樹(shù)數(shù)量也就是有限的)。在這種前提下,B-、B+、B*也就是這樣的數(shù)據(jù)結(jié)構(gòu),多路搜索樹(shù),不再是只有二路。
所謂的平衡就是加上平衡算法,在B樹(shù)在經(jīng)過(guò)多次插入與刪除后,有可能導(dǎo)致不同的結(jié)構(gòu),極端一點(diǎn)就是出現(xiàn)線性的蹩腳樹(shù),通過(guò)平衡算法(左旋和右旋),使樹(shù)的節(jié)點(diǎn)分布均勻,是樹(shù)的查找算法等同于二分查找。所以對(duì)于樹(shù)而言要提高查找的效率,一個(gè)是保存平衡;另一個(gè)是減少樹(shù)的高度。
B-樹(shù)
基于減少樹(shù)的高度上,B-樹(shù)是一種多路搜索樹(shù),并不是二叉的。如下圖所示:
特點(diǎn):所有的非葉子結(jié)點(diǎn)最多有M個(gè)兒子(且M>2)。
根結(jié)點(diǎn)的兒子數(shù)為[2, M],其它非葉子結(jié)點(diǎn)的兒子數(shù)為[M/2, M]。
每個(gè)結(jié)點(diǎn)存放至少M(fèi)/2-1(取上整)和至多M-1個(gè)關(guān)鍵字;(至少2個(gè)關(guān)鍵字)。
非葉子結(jié)點(diǎn)的關(guān)鍵字個(gè)數(shù)=指向兒子的指針個(gè)數(shù)-1。
非葉子結(jié)點(diǎn)的關(guān)鍵字中從左到右由大到小排序。即A[1]
非葉子結(jié)點(diǎn)的指針:P[1], P[2], …, P[M];其中P[1]指向關(guān)鍵字小于K[1]的子樹(shù),其它P[i]指向關(guān)鍵字屬于(K[i-1], K[i])范圍的子樹(shù),最后一個(gè)指針P[M]指向大于隨后一個(gè)關(guān)鍵字A[M-1]范圍的值。
關(guān)鍵字集合分布在整顆樹(shù)中,并且只會(huì)在節(jié)點(diǎn)中出現(xiàn)一次。
搜索可能在非子葉節(jié)點(diǎn)或者子葉節(jié)點(diǎn)結(jié)束,即非子葉節(jié)點(diǎn)也存儲(chǔ)數(shù)據(jù)的身,這個(gè)與B+樹(shù)有根本區(qū)別。
所有葉子結(jié)點(diǎn)位于同一層。
缺點(diǎn):
當(dāng)數(shù)據(jù)量大的時(shí)候不是依然會(huì)查詢到最底層的葉子節(jié)點(diǎn)。這就是B-樹(shù)的缺點(diǎn),但是相比B樹(shù)而言已經(jīng)優(yōu)化了很多。
B-樹(shù)的性能總是等價(jià)于二分查找(與M值無(wú)關(guān)),也就沒(méi)有B樹(shù)平衡的問(wèn)題。由于M/2的限制,在插入結(jié)點(diǎn)時(shí),如果結(jié)點(diǎn)已滿,需要將結(jié)點(diǎn)分裂為兩個(gè)各占M/2的結(jié)點(diǎn);刪除結(jié)點(diǎn)時(shí),需將兩個(gè)不足M/2的兄弟結(jié)點(diǎn)合并。
B+樹(shù)
B+樹(shù)是B-樹(shù)的變體,也是一種多路搜索樹(shù)。如下圖所示:
B+基本與B-樹(shù)同,以下是與B-樹(shù)的區(qū)別:非葉子結(jié)點(diǎn)的指針與關(guān)鍵字個(gè)數(shù)相等,而B(niǎo)-樹(shù)的關(guān)鍵字=指針個(gè)數(shù)-1;
指針P[i],指向關(guān)鍵字值屬于[K[i], K[i+1])范圍的子樹(shù),而在B-樹(shù)是開(kāi)區(qū)間。
所有葉子結(jié)點(diǎn)增加一個(gè)指針,指向下一個(gè)的兄弟葉子節(jié)點(diǎn)。
所有關(guān)鍵字都出現(xiàn)在葉子結(jié)點(diǎn)的鏈表中(稠密索引),且鏈表中的關(guān)鍵字恰好是有序的,搜索只會(huì)在葉子節(jié)點(diǎn)結(jié)束,葉子節(jié)點(diǎn)存儲(chǔ)所有關(guān)鍵字的值。
不可能在非葉子結(jié)點(diǎn)命中;非葉子結(jié)點(diǎn)相當(dāng)于是葉子結(jié)點(diǎn)的索引(稀疏索引),葉子結(jié)點(diǎn)相當(dāng)于是存儲(chǔ)。
B樹(shù)與B+樹(shù)的區(qū)別:
所有的葉子節(jié)點(diǎn)包含了全部關(guān)鍵子信息,及指向含有這些關(guān)鍵字記錄的指針,且葉子結(jié)點(diǎn)本身依關(guān)鍵字的大小自小而大的順序鏈接。(而B(niǎo)樹(shù)的葉子節(jié)點(diǎn)并沒(méi)有包括全部需要查找的信息)。
所有的非終端結(jié)點(diǎn)可以看成是索引部分,結(jié)點(diǎn)中僅含有其子樹(shù)根結(jié)點(diǎn)中最大(或最小)關(guān)鍵字。(而B(niǎo)樹(shù)的非終節(jié)點(diǎn)也包含需要查找的有效信息)。
這些鏈指針在鏈表中是有序存儲(chǔ)的,在搜索中能省大量的時(shí)間。那這些鏈指針可不可以加在所有的節(jié)點(diǎn)中呢,答案是可以的,除了根節(jié)點(diǎn),所有的節(jié)點(diǎn)都可以加上鏈指針。這就是B*樹(shù)索引。
B*樹(shù)
B*樹(shù)是在B+樹(shù)的基礎(chǔ)上,在B+樹(shù)的非根和非葉子結(jié)點(diǎn)增加指向兄弟的指針,將結(jié)點(diǎn)的最低利用率從1/2提高到2/3。
特點(diǎn):B*樹(shù)定義了非葉子結(jié)點(diǎn)關(guān)鍵字個(gè)數(shù)至少為(2/3)M,即塊的最低使用率為2/3(代替B+樹(shù)的1/2)
在非根和非葉子結(jié)點(diǎn)增加指向兄弟的指針。
B+樹(shù)與B*樹(shù)的區(qū)別:
(1)B+樹(shù)的分裂:當(dāng)一個(gè)結(jié)點(diǎn)滿時(shí),分配一個(gè)新的結(jié)點(diǎn),并將原結(jié)點(diǎn)中1/2的數(shù)據(jù)復(fù)制到新結(jié)點(diǎn),最后在父結(jié)點(diǎn)中增加新結(jié)點(diǎn)的指針;B+樹(shù)的分裂只影響原結(jié)點(diǎn)和父結(jié)點(diǎn),而不會(huì)影響兄弟結(jié)點(diǎn),所以它不需要指向兄弟的指針。
(2)B*樹(shù)的分裂:當(dāng)一個(gè)結(jié)點(diǎn)滿時(shí),如果它的下一個(gè)兄弟結(jié)點(diǎn)未滿,那么將一部分?jǐn)?shù)據(jù)移到兄弟結(jié)點(diǎn)中,再在原結(jié)點(diǎn)插入關(guān)鍵字,最后修改父結(jié)點(diǎn)中兄弟結(jié)點(diǎn)的關(guān)鍵字(因?yàn)樾值芙Y(jié)點(diǎn)的關(guān)鍵字范圍改變了);如果兄弟也滿了,則在原結(jié)點(diǎn)與兄弟結(jié)點(diǎn)之間增加新結(jié)點(diǎn),并各復(fù)制1/3的數(shù)據(jù)到新結(jié)點(diǎn),最后在父結(jié)點(diǎn)增加新結(jié)點(diǎn)的指針。結(jié)論:
所以,B*樹(shù)分配新結(jié)點(diǎn)的概率比B+樹(shù)要低,空間使用率更高。
關(guān)于回表查詢:
比如select name from table where id=?,如果name沒(méi)有索引,那在查詢的時(shí)候先得得到的是id對(duì)應(yīng)這條數(shù)據(jù)所在的行數(shù)。拿著這個(gè)行數(shù),再去表中查詢這條數(shù)據(jù),得到name字段。而拿著這個(gè)行數(shù)去得到name字段的動(dòng)作,就是回表查詢。
我們?nèi)绾伪苊饣乇聿樵兡?#xff0c;首先就是不要用 ” * “ 查詢,因?yàn)檫@時(shí)候會(huì)默認(rèn)查詢的字段沒(méi)有索引,必定進(jìn)行回表查詢。
長(zhǎng)按訂閱更多面經(jīng)分享
總結(jié)
以上是生活随笔為你收集整理的b树与b+树的区别_面试必考:B树、B树、B+树、B*树图文详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 什么是两行轨道根数
- 下一篇: 列名无效如何解决_XSKY ClickH