數據結構第11節: B樹

B樹是一種自平衡的樹數據結構,它能夠保持數據排序,并且在插入、刪除和查找操作中具有對數時間復雜度。B樹廣泛應用于文件系統、數據庫和索引中,因為它們可以有效地處理大量數據。

B樹的特點:

  1. 所有葉子節點都位于同一層。
  2. 每個節點可以有多個子節點(至少兩個,最多為某個特定的最大值)。
  3. 節點包含一個關鍵字列表,這些關鍵字將子樹分為不同的范圍。
  4. 節點的關鍵字數量總是小于或等于其子節點的數量減一。
  5. 每個節點的關鍵字都是按照升序排列的。

下面是一個Python實現的B樹:

class BTreeNode:def __init__(self, t, leaf=False):self.t = tself.leaf = leafself.keys = []self.children = []class BTree:def __init__(self, t):self.root = BTreeNode(t, True)self.t = tdef insert(self, k):root = self.rootif len(root.keys) == (2 * self.t) - 1:s = BTreeNode(self.t, False)self.root = ss.children.insert(0, root)self.split_child(s, 0)self.insert_non_full(s, k)else:self.insert_non_full(root, k)def insert_non_full(self, x, k):i = len(x.keys) - 1if x.leaf:x.keys.append((None, None))while i >= 0 and k[0] < x.keys[i][0]:x.keys[i + 1] = x.keys[i]i -= 1x.keys[i + 1] = kelse:while i >= 0 and k[0] < x.keys[i][0]:i -= 1i += 1if len(x.children[i].keys) == (2 * self.t) - 1:self.split_child(x, i)if k[0] > x.keys[i][0]:i += 1self.insert_non_full(x.children[i], k)def split_child(self, x, i):t = self.ty = x.children[i]z = BTreeNode(t, y.leaf)x.children.insert(i + 1, z)x.keys.insert(i, y.keys[t - 1])z.keys = y.keys[t: (2 * t) - 1]y.keys = y.keys[0: t - 1]if not y.leaf:z.children = y.children[t: 2 * t]y.children = y.children[0: t - 1]def delete(self, k):# deletion code here...passdef search(self, k):# search code here...pass

在這個例子中,我們定義了兩個類:BTreeNodeBTreeBTreeNode 類表示B樹中的每個節點,而 BTree 類表示整個B樹。我們實現了插入和分裂操作,但刪除和搜索操作尚未實現。

案例分析:

假設我們要創建一個t=3的B樹,并插入以下關鍵字:(10, ‘a’), (20, ‘b’), (30, ‘c’), (40, ‘d’), (50, ‘e’)。

首先,我們創建一個空的B樹,然后插入第一個關鍵字 (10, ‘a’)。由于樹是空的,這個關鍵字將成為根節點的唯一關鍵字。

接下來,我們插入第二個關鍵字 (20, ‘b’)。因為根節點還沒有達到最大容量(2 * t - 1 = 5),我們可以直接將新關鍵字插入到適當的位置。

然后,我們插入第三個關鍵字 (30, ‘c’)。同樣地,由于根節點還沒有達到最大容量,我們可以直接將新關鍵字插入到適當的位置。

接下來,我們插入第四個關鍵字 (40, ‘d’)。此時,根節點已達到最大容量(5),我們需要創建一個新的父節點,并將根節點分裂成兩個子節點。我們將根節點的中間關鍵字 (20, ‘b’) 移動到新的父節點上,然后將剩下的關鍵字分別放入左右子節點。

最后,我們插入第五個關鍵字 (50, ‘e’)。由于根節點的右子節點還沒有達到最大容量,我們可以直接將新關鍵字插入到適當的位置。

最終的B樹如下所示:

          (20, 'b')/     \(10, 'a')   (30, 'c')\(40, 'd')\(50, 'e')

在上一個案例中,我們構建了一個t=3的B樹并插入了一些關鍵字。現在,讓我們繼續分析如何從這個B樹中刪除一個關鍵字,例如 (20, ‘b’)。

在B樹中,刪除操作可能涉及到以下步驟:

  1. 查找要刪除的關鍵字。
  2. 如果找到的關鍵字在葉節點中,則直接刪除。
  3. 如果找到的關鍵字在非葉節點中,則需要找到后繼或前驅節點,用它來替換要刪除的關鍵字,然后遞歸地刪除該后繼或前驅節點。
  4. 在刪除節點后,如果該節點的關鍵字數量低于最小限制(t-1),則可能需要與相鄰的兄弟節點合并或重新分配關鍵字以保持B樹的平衡。

現在,我們來刪除 (20, ‘b’)。

  1. 首先,我們在B樹中查找關鍵字 (20, ‘b’)。在本例中,(20, ‘b’) 是根節點的關鍵字。

  2. 因為 (20, ‘b’) 在非葉節點中,我們需要找到它的后繼節點。后繼節點是當前節點右側子樹中的最小關鍵字。在本例中,后繼節點是 (30, ‘c’)。

  3. 我們用 (30, ‘c’) 替換 (20, ‘b’)。現在,B樹如下所示:

          (30, 'c')/     \(10, 'a')   (40, 'd')\(50, 'e')
  1. 現在,我們需要遞歸地刪除 (30, ‘c’)。但是,(30, ‘c’) 已經被用作替換,因此不需要進一步刪除。

  2. 下一步是檢查是否有節點的關鍵字數量低于最小限制(t-1)。在這種情況下,根節點只有一個關鍵字,這滿足了最小限制。因此,我們不需要進行任何額外的操作。

最終的B樹如下所示:

          (30, 'c')/     \(10, 'a')   (40, 'd')\(50, 'e')

如果我們繼續向此B樹中添加或刪除關鍵字,B樹將自動進行調整,以保持平衡和排序特性。這種自平衡和排序特性使得B樹非常適合用于大型數據集和外部存儲,如文件系統、數據庫和索引。

在之前的案例分析中,我們討論了如何在B樹中插入和刪除關鍵字。現在,讓我們通過實際的源代碼實現來進一步了解B樹的刪除操作。

在我們之前給出的B樹代碼示例中,delete 方法尚未實現。為了實現刪除操作,我們需要添加以下代碼:

def delete(self, k):root = self.rootself.delete_entry(root, k)def delete_entry(self, x, k):i = 0while i < len(x.keys) and k[0] > x.keys[i][0]:i += 1if x.leaf:if i < len(x.keys) and x.keys[i][0] == k[0]:x.keys.pop(i)returnif i < len(x.keys) and x.keys[i][0] == k[0]:return self.delete_internal_node(x, k, i)elif len(x.children[i].keys) >= self.t:self.delete_entry(x.children[i], k)else:if i != 0 and i + 2 < len(x.children):if len(x.children[i - 1].keys) >= self.t:self.move_right(x, i)elif len(x.children[i + 1].keys) >= self.t:self.move_left(x, i)else:self.merge(x, i)self.delete_entry(x.children[i], k)def delete_internal_node(self, x, k, i):if x.leaf:if x.keys[i][0] == k[0]:x.keys.pop(i)returnif len(x.children[i].keys) >= self.t:x.keys[i] = self.find_predecessor(x.children[i])self.delete_entry(x.children[i], x.keys[i])elif len(x.children[i + 1].keys) >= self.t:x.keys[i] = self.find_successor(x.children[i + 1])self.delete_entry(x.children[i + 1], x.keys[i])else:self.merge(x, i)self.delete_entry(x.children[i], k)def find_predecessor(self, x):while not x.leaf:x = x.children[-1]return x.keys[-1]def find_successor(self, x):while not x.leaf:x = x.children[0]return x.keys[0]def move_right(self, x, i):child = x.children[i]sibling = x.children[i + 1]child.keys.append(x.keys[i])x.keys[i] = sibling.keys[0]sibling.keys.pop(0)if not child.leaf:child.children.append(sibling.children[0])sibling.children.pop(0)def move_left(self, x, i):child = x.children[i]sibling = x.children[i - 1]child.keys.insert(0, x.keys[i - 1])x.keys[i - 1] = sibling.keys[-1]sibling.keys.pop()if not child.leaf:child.children.insert(0, sibling.children[-1])sibling.children.pop()def merge(self, x, i):child = x.children[i]sibling = x.children[i + 1]child.keys.append(x.keys[i])child.keys += sibling.keyschild.children += sibling.childrenx.keys.pop(i)x.children.pop(i + 1)

現在,我們可以使用以下代碼測試B樹的刪除操作:

tree = BTree(3)
tree.insert((10, 'a'))
tree.insert((20, 'b'))
tree.insert((30, 'c'))
tree.insert((40, 'd'))
tree.insert((50, 'e'))tree.delete((20, 'b'))

這將刪除關鍵字 (20, ‘b’) 并自動調整B樹以保持平衡。最終的B樹如下所示:

          (30, 'c')/     \(10, 'a')   (40, 'd')\(50, 'e')

在這個示例中,我們實現了B樹的刪除操作,包括查找要刪除的關鍵字、用后繼或前驅節點替換要刪除的關鍵字、遞歸地刪除后繼或前驅節點以及維護B樹的平衡。這些操作確保了B樹在插入、刪除和查找操作中始終具有對數時間復雜度,使其成為處理大量數據和外部存儲的理想數據結構。

B樹的性質可以通過一個表格的形式來總結,這樣可以清晰地列出B樹的關鍵特征。以下是一個關于B樹性質的表格:

特性描述
定義B樹是一種自平衡的多路搜索樹,用于快速查找、插入和刪除操作。
階數B樹的階數 m 定義了每個節點最多有多少個子節點。
最小度數B樹的最小度數 t,等于 m/2 向上取整。
關鍵字數量每個節點最多有 m-1 個關鍵字,至少有 t-1 個關鍵字(對于非根節點)。
子節點數量每個節點至少有 t 個子節點(對于非根節點),最多有 m 個子節點。
根節點根節點至少有一個關鍵字,最多有 m-1 個關鍵字。
葉子節點所有葉子節點都位于同一層,并且不含有子節點。
關鍵字順序節點中的關鍵字按升序排列。
分割規則當一個節點的關鍵字數量超過 m-1 時,節點將被分割。
分割細節分割時,中間關鍵字被提升到父節點,形成兩個新的子節點。
平衡性B樹的所有路徑從根到葉的長度相同。

此外,下面是關于B樹插入、刪除和查找操作的表格:

操作描述
插入當插入一個關鍵字時,如果節點未滿,則直接插入;如果節點已滿,則節點將被分割,中間關鍵字提升到父節點。
刪除刪除一個關鍵字可能涉及替換內部節點的關鍵字(用前驅或后繼),然后從葉節點刪除該關鍵字。如果刪除導致節點的關鍵字數量低于 t-1,則需要與兄弟節點合并或重新分配關鍵字。
查找從根節點開始,比較關鍵字,向下遍歷到正確的子節點,直到找到關鍵字或到達葉節點。

這些表格提供了B樹的基本結構和操作的概覽,幫助理解其設計和功能。B樹的設計目的是為了優化磁盤I/O,因為磁盤讀寫通常涉及較大的塊,B樹允許在每次磁盤訪問時讀取更多的數據。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/41731.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/41731.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/41731.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【】AI八股-神經網絡相關

Deep-Learning-Interview-Book/docs/深度學習.md at master amusi/Deep-Learning-Interview-Book GitHub 網上相關總結&#xff1a; 小菜雞寫一寫基礎深度學習的問題&#xff08;復制大佬的&#xff0c;自己復習用&#xff09; - 知乎 (zhihu.com) CV面試問題準備持續更新貼 …

.net 調用海康SDK的跨平臺解決方案

??歡迎點贊 :?? 收藏 ?留言 ?? 如有錯誤敬請指正,賜人玫瑰,手留余香!??本文作者:由webmote 原創??作者格言:新的征程,我們面對的不僅僅是技術還有人心,人心不可測,海水不可量,唯有技術,才是深沉黑夜中的一座閃爍的燈塔序言 上2篇海康SDK使用以及常見的坑…

PCL 點云PFH特征描述子

點云PFH特征描述子 一、概述1.1 概念1.2 算法原理一、代碼實現二、結果示例一、概述 1.1 概念 點特征直方圖PFH(Point Feature Histograms)描述子:用于表示點云中每個點的局部幾何形狀信息,它是一種直方圖描述子,包括了點云的法線方向和曲率信息,PFH描述子可以幫助區分不同…

深入Django(八)

掌握Django的管理后臺 引言 在前七天的教程中&#xff0c;我們介紹了Django的基礎架構、模型、視圖、模板、URL路由、表單系統以及數據庫遷移。今天&#xff0c;我們將深入了解Django的管理后臺&#xff0c;這是一個功能強大的內置管理界面&#xff0c;用于創建、更新、查看和…

【JavaEE精煉寶庫】文件操作(1)——基本知識 | 操作文件——打開實用性編程的大門

目錄 一、文件的基本知識1.1 文件的基本概念&#xff1a;1.2 樹型結構組織和目錄&#xff1a;1.3 文件路徑&#xff08;Path&#xff09;&#xff1a;1.4 二進制文件 VS 文本文件&#xff1a;1.5 其它&#xff1a; 二、Java 操作文件2.1 方法說明&#xff1a;2.2 使用演示&…

QT面試筆記總計

一 Qt 保證多線程安全? 使互斥鎖保證多線程安全性。QMutex類、。使用讀寫鎖保證多線程安全性&#xff0c;QReadWriteLock。使用信號和槽機制保證多線程安全性。使用顯示切換保證多線程安全性。QTread類。 Qt 中的事件與信號的區別? 事件與信號的實現機制不同&#xff1b;事…

HCIA綜合實驗

學習新思想&#xff0c;爭做新青年。今天學習的是HCIA綜合實驗&#xff01; 實驗拓撲 實驗需求 總部&#xff1a; 1、除了SW8 SW9是三層交換機&#xff0c;其他交換機均為2層交換機。 2、GW為總部的出口設備&#xff0c;使用單臂路由技術&#xff0c;VLAN10,20,100的網關都在GW…

ERROR: “armeabi-v7a“ not supported for HarmonyOS

IDE 從 devecostudio-mac-4.1.3.700 升級至 devecostudio-mac-5.0.3.403 后拋出了如下異常: ERROR: "armeabi-v7a" not supported for HarmonyOS. 解決辦法 一.entry/build-profile.json5 需 entry/build-profile.json5 的 abiFilters 中移除 "armeabi-v7a&qu…

計算機網絡體系結構詳解:協議與分層

在學習計算機網絡時&#xff0c;理解網絡協議與分層體系結構是至關重要的。本文將詳細介紹這些概念&#xff0c;幫助基礎小白快速入門。 1. 什么是網絡協議 網絡協議是計算機網絡中用于數據交換的規則和標準。這些規則規定了數據格式、時序以及發送和接收數據時的動作。網絡協…

Unity3D瓦片地圖輔助定位工具

介紹 該工具用于TileMap的瓦片輔助定位&#xff0c;通過鍵盤或鼠標按瓦片尺寸0到1的比例作為單次移動值移動定位點游戲對象。當采用定位點游戲對象映射瓦片時&#xff0c;可使用該工具來移動定位點游戲對象&#xff0c;在新版本Unity3D的TileMap編輯器中可使用GameObject Brush…

基于java+springboot+vue實現的流浪動物管理系統(文末源碼+Lw)277

摘 要 在如今社會上&#xff0c;關于信息上面的處理&#xff0c;沒有任何一個企業或者個人會忽視&#xff0c;如何讓信息急速傳遞&#xff0c;并且歸檔儲存查詢&#xff0c;采用之前的紙張記錄模式已經不符合當前使用要求了。所以&#xff0c;對流浪動物信息管理的提升&…

【React】React18 Hooks之useState

目錄 useState案例1&#xff08;直接修改狀態&#xff09;案例2&#xff08;函數式更新&#xff09;案例3&#xff08;受控表單綁定&#xff09;注意事項1&#xff1a;set函數不會改變正在運行的代碼的狀態注意事項2&#xff1a;set函數自動批量處理注意事項3&#xff1a;在下次…

實現基于Spring Security的權限管理系統

實現基于Spring Security的權限管理系統 大家好&#xff0c;我是免費搭建查券返利機器人省錢賺傭金就用微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01; 在現代Web應用中&#xff0c;權限管理系統是至關重要的組成部分。通過…

[數據集][目標檢測]護目鏡檢測數據集VOC+YOLO格式888張1類別

數據集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路徑的txt文件&#xff0c;僅僅包含jpg圖片以及對應的VOC格式xml文件和yolo格式txt文件) 圖片數量(jpg文件個數)&#xff1a;888 標注數量(xml文件個數)&#xff1a;888 標注數量(txt文件個數)&#xff1a;888 標注類別…

ORB 特征點提取

FAST關鍵點 選取像素p&#xff0c;假設它的亮度為Ip&#xff1b; . 設置一個閾值T&#xff08;比如Ip的20%&#xff09;&#xff1b; 以像素p為中心&#xff0c;選取半徑為3的圓上的16個像素點&#xff1b; 假如選取的圓上&#xff0c;有連續的N個點的亮度大于IpT或小于…

Redis 八股文

標題 1. Redis主從同步原理&#xff1a;判斷下線的條件:故障轉移如何保證Sentinel高可用 1. Redis主從同步原理&#xff1a; 1、slave執行命令向master建立連接 2、master執行bgsave&#xff08;后臺存儲&#xff09;&#xff0c;生成rdb快照&#xff08;redis備份方式&#x…

FreeRTOS中vTaskDelay 和 xTaskDelayUntil 的區別?

vTaskDelay 和 xTaskDelayUntil 是 FreeRTOS 提供的兩種不同任務延遲函數&#xff0c;各自有其適用的場景和優缺點。vTaskDelay 適用于簡單的延遲操作&#xff0c;而 xTaskDelayUntil 提供了精確的周期控制能力。在設計 FreeRTOS 應用程序時&#xff0c;根據任務的時間要求選擇…

日志自動分析-Web---360星圖GoaccessALBAnolog

目錄 1、Web-360星圖(IIS/Apache/Nginx) 2、Web-GoAccess &#xff08;任何自定義日志格式字符串&#xff09; 源碼及使用手冊 安裝goaccess 使用 輸出 3-Web-自寫腳本&#xff08;任何自定義日志格式字符串&#xff09; 4、Web-機器語言analog&#xff08;任何自定義日…

游戲AI的創造思路-技術基礎-強化學習(1)

我們“強化”一下機器的“學習”&#xff0c;讓機器變得更強~~~~ 目錄 1. 強化學習的定義 2. 發展歷史 3. 強化學習的基本概念和函數 3.1. 基本概念和函數 3.1.1. 基本概念和函數 3.1.2. Q函數 3.1.2.1. 定義與作用 3.1.2.2. 數學表示 3.1.2.3. 更新規則 3.1.2.4. 算…

AI時代算法面試:揭秘高頻算法問題與解答策略

三種決策樹算法的特點和區別 ID3算法&#xff1a;基本的決策樹算法&#xff0c;適用于簡單的分類問題C4.5算法&#xff1a;改進了ID3算法&#xff0c;適用于更復雜的分類問題&#xff0c;可以處理連續型數據和缺失值CART算法&#xff1a;更加通用的決策樹算法&#xff0c;適用于…