b 树查找时间复杂度_你心里是没点B树吗?
點(diǎn)擊上方“零一視界”,選擇“星標(biāo)”公眾號(hào)
資源干貨,第一時(shí)間送達(dá)
1 引言
數(shù)據(jù)庫(kù)的增刪改查等操作是開(kāi)發(fā)過(guò)程中最為常見(jiàn)也是尤為重要的,尤其是現(xiàn)在大數(shù)據(jù)的興起,導(dǎo)致數(shù)據(jù)存儲(chǔ)量急劇增加,提升數(shù)據(jù)的操作效率就變得尤為關(guān)鍵。
大部分?jǐn)?shù)據(jù)庫(kù)的索引都采用樹(shù)的結(jié)構(gòu)存儲(chǔ),這是因?yàn)闃?shù)的查詢(xún)效率相對(duì)較高,且保持有序。
對(duì)于二叉搜索樹(shù)的時(shí)間復(fù)雜度是O(logN),在算法以及邏輯上來(lái)分析,二叉搜索樹(shù)的查找速度以及數(shù)據(jù)比較次數(shù)都是較小的。
但是我們不得不考慮一個(gè)新的問(wèn)題。
數(shù)據(jù)量是遠(yuǎn)大于內(nèi)存大小的,那我們?cè)诓檎覕?shù)據(jù)時(shí)并不能將全部數(shù)據(jù)同時(shí)加載至內(nèi)存。既然不能全部加載至內(nèi)存中就只能逐步的去加載磁盤(pán)中某個(gè)頁(yè),簡(jiǎn)而言之就是逐一的去加載磁盤(pán),加數(shù)據(jù)分塊的加載至內(nèi)存進(jìn)行查找與比較。
例如:在圖1.1所示的樹(shù)中查找10,樹(shù)中的每個(gè)節(jié)點(diǎn)代表一個(gè)磁盤(pán)頁(yè)。每次訪(fǎng)問(wèn)一個(gè)新節(jié)點(diǎn)代表一次磁盤(pán)IO。
圖1.0圖1.1通過(guò)查找過(guò)程可以看出,磁盤(pán)IO次數(shù)與樹(shù)的高度相關(guān),在最壞情況下,磁盤(pán)IO次數(shù)等于樹(shù)的高度。由于磁盤(pán)IO過(guò)程是相對(duì)耗時(shí)效率較低的,因此,在設(shè)計(jì)數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)時(shí)需要降低樹(shù)的高度,即將一棵“瘦高”的樹(shù)變得“矮胖”。
當(dāng)數(shù)據(jù)數(shù)目相同,在保持有序前提下,降低樹(shù)高度,只需將節(jié)點(diǎn)中存儲(chǔ)的key值增加,即二叉搜索樹(shù)中每個(gè)節(jié)點(diǎn)只有一個(gè)key,現(xiàn)將一個(gè)節(jié)點(diǎn)中存儲(chǔ)多個(gè)key,得到的樹(shù)即為B樹(shù)。
2 定義
B樹(shù)也稱(chēng)B-樹(shù),B-樹(shù)直接讀作B樹(shù),不能因?yàn)橛小?”號(hào)就讀作B減樹(shù),它是一顆多路平衡查找樹(shù)。我們描述一顆B樹(shù)時(shí)需要指定它的階數(shù),階數(shù)表示了一個(gè)結(jié)點(diǎn)最多有多少個(gè)孩子結(jié)點(diǎn),一般用字母m表示階數(shù)。當(dāng)m取2時(shí),就是我們常見(jiàn)的二叉搜索樹(shù),m為3時(shí)是2-3樹(shù)。
一顆m階的B樹(shù)定義如下:
(1)每個(gè)結(jié)點(diǎn)最多有m-1個(gè)關(guān)鍵字。
(2)根結(jié)點(diǎn)最少可以只有1個(gè)關(guān)鍵字。
(3)非根結(jié)點(diǎn)至少有Math.ceil(m/2)-1個(gè)關(guān)鍵字。Math.ceil(m/2)含義是向上取整。例如Math.ceil(4.5) = 5。
(4)每個(gè)結(jié)點(diǎn)中的關(guān)鍵字都按照從小到大的順序排列,每個(gè)關(guān)鍵字的左子樹(shù)中的所有關(guān)鍵字都小于它,而右子樹(shù)中的所有關(guān)鍵字都大于它。
(5)所有葉子結(jié)點(diǎn)都位于同一層,或者說(shuō)根結(jié)點(diǎn)到每個(gè)葉子結(jié)點(diǎn)的長(zhǎng)度都相同。
3 查找
B-樹(shù)的查找其實(shí)是對(duì)二叉搜索樹(shù)查找的擴(kuò)展, 與二叉搜索樹(shù)不同的地方是,B-樹(shù)中每個(gè)節(jié)點(diǎn)有不止一棵子樹(shù)。在B-樹(shù)中查找某個(gè)結(jié)點(diǎn)時(shí),需要先判斷要查找的結(jié)點(diǎn)在哪棵子樹(shù)上,然后在結(jié)點(diǎn)中逐個(gè)查找目標(biāo)結(jié)點(diǎn)。B樹(shù)的查找過(guò)程相對(duì)簡(jiǎn)單,與二叉搜索樹(shù)類(lèi)似,因此不再贅述。
4 插入
B樹(shù)的插入操作是指在樹(shù)種插入一條新記錄,即(key, value)的鍵值對(duì)。如果B樹(shù)中已存在需要插入的鍵值對(duì),則用需要插入的value替換舊的value。若B樹(shù)不存在這個(gè)key,則一定是在葉子結(jié)點(diǎn)中進(jìn)行插入操作。
4.1 插入流程
B樹(shù)的插入流程如下:
??(1)根據(jù)要插入的key的值,對(duì)B樹(shù)執(zhí)行查找操作,查找到待插入數(shù)據(jù)的當(dāng)前節(jié)點(diǎn)位置。
??(2)判斷當(dāng)前結(jié)點(diǎn)key的個(gè)數(shù)是否小于等于m-1,若滿(mǎn)足,則結(jié)束直接插入數(shù)據(jù),否則,進(jìn)行第(3)步。
??(3)以結(jié)點(diǎn)中間的key為中心分裂成左右兩部分,然后將這個(gè)中間的key插入到父結(jié)點(diǎn)中,這個(gè)key的左子樹(shù)指向分裂后的左半部分,這個(gè)key的右子支指向分裂后的右半部分,然后將當(dāng)前結(jié)點(diǎn)指向父結(jié)點(diǎn),繼續(xù)進(jìn)行第(3)步。
4.2 實(shí)例圖解
下面以5階B樹(shù)為例,介紹B樹(shù)的插入操作,在5階B樹(shù)中,結(jié)點(diǎn)最多有4個(gè)key,最少有2個(gè)key。
插入圖解:1:插入38,此時(shí)為空樹(shù),直接插入,并作為根節(jié)點(diǎn)。繼續(xù)插入22、76、40,符合情形(2),直接插入。繼續(xù)插入51,符合情形(3),執(zhí)行分裂。
img2:按照相同的步驟繼續(xù)插入13、21。插入39,符合情形(3),導(dǎo)致節(jié)點(diǎn)分裂。選擇中值22作為父節(jié)點(diǎn),并將22節(jié)點(diǎn)上移,與40節(jié)點(diǎn)進(jìn)行合并。img3:按照同樣的插入規(guī)則,繼續(xù)向樹(shù)中插入key為30、27、33、36、35、34、24、29的數(shù)據(jù)。插入完成后,繼續(xù)插入key為26的數(shù)據(jù),插入之后需要執(zhí)行節(jié)點(diǎn)分裂。img4:將key為27的數(shù)據(jù)節(jié)點(diǎn)上移至父節(jié)點(diǎn),此時(shí)父節(jié)點(diǎn)已經(jīng)有4個(gè)key,插入key27的數(shù)據(jù)后需要執(zhí)行節(jié)點(diǎn)分裂。在插入key為26的數(shù)據(jù)后,導(dǎo)致根節(jié)點(diǎn)發(fā)生分裂,樹(shù)的高度加1。img4.3 性能分析
B樹(shù)插入過(guò)程首先需要執(zhí)行一次查找操作,B樹(shù)的查找操作的時(shí)間復(fù)雜度為O(mlogmn)。其中m為B樹(shù)的階數(shù),n為B樹(shù)中key的數(shù)目。在插入過(guò)程,最耗時(shí)的情形即為:插入數(shù)據(jù)后導(dǎo)致根節(jié)點(diǎn)發(fā)生分裂,分裂節(jié)點(diǎn)的操作是常數(shù)級(jí),分裂操作向上回溯的時(shí)間復(fù)雜度為O(h)。因此,B樹(shù)的插入操作的時(shí)間復(fù)雜度近似于查找操作,即O(mlogmn)。
5 刪除
5.1 刪除流程
B樹(shù)的刪除流程如下:
??(1)如果當(dāng)前需要?jiǎng)h除的key位于非葉子結(jié)點(diǎn)上,則用后繼key(這里的后繼key均指后繼記錄的意思)覆蓋要?jiǎng)h除的key,然后在后繼key所在的子支中刪除該后繼key。此時(shí)后繼key一定位于葉子結(jié)點(diǎn)上,這個(gè)過(guò)程和二叉搜索樹(shù)刪除結(jié)點(diǎn)的方式類(lèi)似。刪除這個(gè)記錄后執(zhí)行第2步
??(2)該結(jié)點(diǎn)key個(gè)數(shù)大于等于Math.ceil(m/2)-1,結(jié)束刪除操作,否則執(zhí)行第(3)步。
??(3)如果兄弟結(jié)點(diǎn)key個(gè)數(shù)大于Math.ceil(m/2)-1,則父結(jié)點(diǎn)中的key下移到該結(jié)點(diǎn),兄弟結(jié)點(diǎn)中的一個(gè)key上移,刪除操作結(jié)束。否則,將父結(jié)點(diǎn)中的key下移與當(dāng)前結(jié)點(diǎn)及它的兄弟結(jié)點(diǎn)中的key合并,形成一個(gè)新的結(jié)點(diǎn)。原父結(jié)點(diǎn)中的key的兩個(gè)孩子指針就變成了一個(gè)孩子指針,指向這個(gè)新結(jié)點(diǎn)。然后當(dāng)前結(jié)點(diǎn)的指針指向父結(jié)點(diǎn),重復(fù)第(2)步。
5.2 實(shí)例圖解
刪除圖解:1:首先刪除21,符合情形(2)直接刪除。刪除21后,繼續(xù)刪除27,符合情形(1),使用后繼節(jié)點(diǎn)28替代27,并刪除28。
img2:刪除28后,當(dāng)前節(jié)點(diǎn)只有一個(gè)key,因此需要按照情形(3)調(diào)整。當(dāng)前節(jié)點(diǎn)的兄弟節(jié)點(diǎn)有3個(gè)key,父節(jié)點(diǎn)中key28下移,兄弟節(jié)點(diǎn)中key26上移,調(diào)整結(jié)束。調(diào)整完畢后繼續(xù)刪除32。img3:刪除32后,需要按照情形(3)進(jìn)行調(diào)整,當(dāng)前節(jié)點(diǎn)的兄弟節(jié)點(diǎn)只有2個(gè)key,則將父節(jié)點(diǎn)下移,將當(dāng)前節(jié)點(diǎn)與一個(gè)兄弟節(jié)點(diǎn)合并,調(diào)整完畢。繼續(xù)刪除39,刪除39后按照情形(3)進(jìn)行調(diào)整。img4:當(dāng)前節(jié)點(diǎn)變?yōu)橹缓衚ey40的節(jié)點(diǎn),需要按照情形(3)繼續(xù)調(diào)整,執(zhí)行節(jié)點(diǎn)的合并,合并操作中包含根節(jié)點(diǎn),導(dǎo)致合并之后的樹(shù)的高度減1。img5.3 性能分析
B樹(shù)的刪除操作同樣需要執(zhí)行查找過(guò)程,時(shí)間復(fù)雜度為O(mlogmn)。刪除數(shù)據(jù)過(guò)程與插入過(guò)程類(lèi)似,最壞情況需要回溯O(h)。因此B樹(shù)的刪除操作的時(shí)間復(fù)雜度近似為O(mlogmn)。
6 總結(jié)
B樹(shù)是一種平衡的多路查找樹(shù)。其設(shè)計(jì)思路主要是通過(guò)節(jié)點(diǎn)中存儲(chǔ)不止一個(gè)key,來(lái)降低樹(shù)的高度。同等比較次數(shù)下,樹(shù)的高度小保證磁盤(pán)IO次數(shù)相對(duì)較少,提高查找效率。
推薦閱讀
有趣的學(xué)習(xí)《操作系統(tǒng)真象還原》
數(shù)據(jù)分析必備,《利用Python進(jìn)行數(shù)據(jù)分析》推薦
有趣的算法書(shū)《算法圖解》推薦
輕松學(xué)習(xí)網(wǎng)絡(luò)知識(shí),《圖解HTTP》推薦
歡迎關(guān)注我們,收獲資源干貨!
總結(jié)
以上是生活随笔為你收集整理的b 树查找时间复杂度_你心里是没点B树吗?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python传文件给java_pytho
- 下一篇: vue 2个方法先后执行_有效快速制作工