B树可以采用二叉树的形式吗

问题描述

在关于数据库系统的 CS 考试中,有一个问题被问到使用 B 树进行索引在给定系统中查找记录的最大块访问次数是多少。 B-tree 的顺序是 4,最大条目数是当所有内部节点都是半满时(因为如果它们小于半满,它们将与邻居合并)。因此,当每个节点有 2 个子树指针时,树处于其最高深度(并且最大访问次数等于树的深度)。但这将有效地使树具有与二叉树相同的结构,因为每个节点只保存一个数据和两个指针。

所以问题是:

有了插入和删除的策略,物理上是否可以按照允许树采用这种形式的顺序插入和删除节点,还是会一直合并并减少树的深度?

解决方法

当然可以。

这样的二叉树仅靠插入是不可能实现的,但是一旦在 4 度 b 树中插入了一堆键(数据元素),您就可以从叶子中删除键,以便针对二叉树形状。

您将针对二叉树的特定树高,因此首先进行足够的插入以获得具有该高度的 B 树。然后消除键以减少非二元节点的程度,从树的顶层开始,向下工作。

一个例子

假设您想创建这样一棵高度为 3 的树。为此,我们将值 1 到 13 插入到一棵空树中。这将导致这棵树:

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

start_date = "2019-06-18"
end_date = "2019-06-19"

x0 = '2019-06-18 9:00:00'
x1 = '2019-06-18 17:00:00'

N = 200
df = pd.DataFrame({'DateTime': pd.date_range(start_date,freq='10min',periods=N),'FromGen': 8 * np.exp(-(np.arange(N) - 80) ** 2 / 1000) + np.random.uniform(0,0.4,N),'ToCons': np.random.uniform(1,1.5,N)})

x0 = pd.to_datetime(x0,format="%Y-%m-%d")
x1 = pd.to_datetime(x1,format="%Y-%m-%d")

zeit = df.loc[(df['DateTime'] > start_date) & (df['DateTime'] <= end_date)]

ax = zeit.plot(figsize=(15,10),x="DateTime",y=["FromGen","ToCons"])

ax.set_xlabel("Zeit")
ax.set_ylabel("Wh")
legend = ax.legend(title="comp",loc='upper right',fontsize='large',fancybox=True,labels=['FromGen','ToCons'])
ax.axvline(x=x0,color='red')
ax.axvline(x=x1,color='red')

ax.fill_between(zeit['DateTime'].values,zeit['FromGen'],zeit['ToCons'],where=(zeit['FromGen'] > zeit['ToCons']) & ((zeit['DateTime'] <= x0) | (zeit['DateTime'] >= x1)),interpolate=False,color='#8FF536')
plt.show()

现在为了在我们目前有 [3,6] 的地方只得到一个键,我们需要去掉它的一个子键。所以让我们删除 7 和 8:

删除 8 后,标准算法会将值 5 从 [4,5] “旋转”到其父级,并将父键 (6) 注入我们删除 8 的子级:

                    [9] 
     [3,6]               [12] 
[1,2] [4,5] [7,8]   [10,11]  [13] 

我们仍然有太多孩子在同一个节点,所以我们继续删除6。现在有叶子的合并,这将减少我们最初想要减少的节点:

               [9] 
     [3,5]             [12] 
[1,2] [4]  [6]   [10,11]  [13] 

现在所有非二进制节点都在底层。我们现在可以删除键 2、5 和 11 以获得二叉树:

             [9] 
     [3]               [12] 
[1,5]   [10,11]  [13] 

一般情况

同样的原理也适用于高度较高的树木。只需开始从内部节点的子树中删除非二进制的键,直到它们成为。在某些时候会发生合并,这将减少非二进制节点的程度,最终使它们成为二进制。

如果你从上到下这样做,你会一层一层的二进制,最后底层也是二进制的。