1-数据结构 - B - tree

before

首先要说明的是B树B - tree(Balance - Tree)是一个概念,不要理解为"两颗树",中间的是连接符中横线,而不是减号!
B树和平衡二叉树稍有不同的是B树属于"多叉树",又名"平衡多路查找树",即查找路径不只有两个;数据库索引中大量使用的就是B树和B+树的数据结构,本篇来研究B树。

B树的应用

  • 文件系统:
    - Windows:HPFS文件系统
    - Mac:HFS,HFS+文件系统
    - Linux:ResiserFS,XFS,Ext3FS,JFS文件系统
  • 数据库:
    - Oracle
    - MySQL
    - SQL server

定义

来自维基百科的定义,一个 m 阶的B树是一个有以下属性的树:

  • 每一个节点最多有 m 个子节点
  • 每一个非叶子节点(除根节点)最少有 ⌈m/2⌉ 个子节点
  • 如果根节点不是叶子节点,那么它至少有两个子节点
  • 有 k 个子节点的非叶子节点拥有 k − 1 个键
  • 所有的叶子节点都在同一层,整棵树的高度一致

如上图,每一个内部节点的键将节点的子树分开。例如,如果一个内部节点有3个子节点(子树),那么它就必须有两个键: a1 和 a2 。左边子树的所有值都必须小于 a1 ,中间子树的所有值都必须在 a1 和a2 之间,右边子树的所有值都必须大于 a2 。
内部节点
内部节点是除叶子节点和根节点之外的所有节点。它们通常被表示为一组有序的元素和指向子节点的指针。每一个内部节点拥有最多 U 个,最少 L 个子节点。元素的数量总是比子节点指针的数量少一(元素的数量在 L-1 和 U-1 之间)。U 必须等于 2L 或者 2L-1;因此,每一个内部节点都至少是半满的。U 和 L 之间的关系意味着两个半满的节点可以合并成一个合法的节点,一个全满的节点可以被分裂成两个合法的节点(如果父节点有空间容纳移来的一个元素)。这些特性使得在B树中删除或插入新的值时可以调整树来保持B树的性质。
根节点

根节点拥有的子节点数量的上限和内部节点相同,但是没有下限。例如,当整个树中的元素数量小于 L-1 时,根节点是唯一的节点并且没有任何子节点。

叶子节点

叶子节点对元素的数量有相同的限制,但是没有子节点,也没有指向子节点的指针。

一个深度为n+1 的B树可以容纳的元素数量大约是深度为 n 的B树的 U 倍,但是搜索、插入和删除操作的开销也会增加。和其他的平衡树一样,这一开销增加的速度远远慢于元素数量的增加。

一些平衡树只在叶子节点中存储值,而且叶子节点和内部节点使用不同的结构。B树在每一个节点中都存储值,所有的节点有着相同的结构。然而,因为叶子节点没有子节点,所以可以通过使用专门的结构来提高B树的性能。

生成

先说规则:

  • 生成一个2度的B树,树的度表示一棵树中的节点最多有多少个查找路径,2度的树表示一颗树中的节点最多有2个查找路径。

我们分步骤使用下面的数据来演示一个2度的B树的创建过程:

[8, 11, 19, 27, 28, 51, 52, 55, 56, 72]
[3, 5, 8, 9, 10, 12, 13, 15, 17, 18, 25, 26, 28, 29, 30, 31, 33, 35, 36, 60, 65, 75, 79, 87, 90, 99]
  1. 在一棵空树中插入8,11,每个就节点的键从左小右大顺序排列的:

  1. 再插入19,因为是2度的树,此时的节点有3个键,所以,要进行分裂,提取8,11,19中间的键11作为父节点,并且遵循:父节点的左侧孩子节点比自己小;右侧孩子节点比自己大的规则:

  1. 继续插入27,28,因为这两个值都比父节点11大,所以插在了父节点的右侧孩子节点,此时该孩子节点由19,27,28三个键组成,继续根据中间的键分裂,将27跟父节点11合并组成11,27节点(此时不满足分裂条件);此时父节点遵循:父节点左边的键的孩子节点比该键都小;右边的键的孩子节点比自己大;父节点的两个键中间的孩子节点满足比左爹(父节点的左键)大比右爹(父节点的右键)小的规则。

  1. 继续插入51成为27的子节点,如下图1号;再插入5228,51组成子节点,如下图2号所示,并提取中间值51为父节点,此时父节点便成11,27,51三个键组成的节点,如下图3号所示,符合分裂条件,提取中间值27为父节点,此时需要注意的是1928两个值怎么划分,首先19小于27,所以分给了11这个叶子节点;而2827大,所以分给了51这个叶子节点,又因为比51小,所以成为51节点的左侧孩子节点,如下图4号所示。

  1. 继续插入56,此时5652相安无事;再插入72,和52,56共同组成3个键的节点,提取中间的键5651组成父节点,其过程如下图所示:

此时,一个高度为3的2度B树生成完毕,在理解其分裂过程时,要充分理解其遵循的规则,下图动态的展示了总的过程:

要牢记,上层的叶子节点都会保存其孩子节点的指针,只是在图中没有体现出来。

PS:Selenium生成B树的示例代码
import time
import random
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait

# l = [1, 2, 5, 9, 11, 14, 16, 30, 35, 38, 39, 44, 49, 58, 60, 64, 65, 66, 79, 96]
l = [8, 11, 19, 27, 28, 51, 52, 55, 56, 72]
url = "https://www.cs.usfca.edu/~galles/visualization/BTree.html"
# max_degree 度数
max_degree_3 = "/html/body/div/div[2]/div[1]/table/td[9]/table/tr[1]/td/input"
max_degree_4 = "/html/body/div/div[2]/div[1]/table/td[9]/table/tr[2]/td/input"
max_degree_5 = "/html/body/div/div[2]/div[1]/table/td[9]/table/tr[3]/td/input"
max_degree_6 = "/html/body/div/div[2]/div[1]/table/td[9]/table/tr[4]/td/input"
max_degree_7 = "/html/body/div/div[2]/div[1]/table/td[9]/table/tr[5]/td/input"


driver = webdriver.Chrome()
driver.implicitly_wait(10)
wait = WebDriverWait(driver=driver, timeout=10)

try:
    driver.get(url)
    driver.maximize_window()
    driver.find_element_by_xpath(max_degree_3).click()  # 默认是 3
    for i in l:
        wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="AlgorithmSpecificControls"]/td[1]/input'))).send_keys(i)
        driver.find_element_by_xpath('//*[@id="AlgorithmSpecificControls"]/td[2]/input').click()
        time.sleep(3)
except Exception as e:
    print(e)

finally:
    time.sleep(60)
    driver.quit()

搜索

B树的搜索和二叉搜索树类似。从根节点开始,从上到下递归的遍历树。在每一层上,搜索的范围被减小到包含了搜索值的子树中。子树值的范围被它的父节点的键确定。
下图展示了B树的搜索过程:

删除


that's all,see also:

平衡二叉树、B树、B+树、B*树 理解其中一种你就都明白了 | 编程之法:面试和算法心得:B树篇 | (重点)MySQL(入门篇25)MySQL BTree索引背后的数据结构及算法原理

posted @ 2020-09-14 11:41  听雨危楼  阅读(653)  评论(0编辑  收藏  举报