我认为您的页面创建过程是颠倒的。当一个节点拆分它不会创造更多的节点下来(在你的儿子命名节点)的层次结构。相反,它向根部向上创建更多。正如书中所说
请注意,生长在树的顶部,这是B树的固有特征,以确保重要的属性是:它始终使所有叶子处于同一水平,并且每个与根不同的节点至少50%已满。
(我的重点。)
从链接的电子书中:
定义5.1 AB – m阶的树(m≥3)...每个节点最多包含m − 1个键
该练习针对m = 3,因此每个节点最多2个键。
前两个键很简单-进入第一页:
A:[1,2]
我将使用ASCII艺术。我将按照创建它们的顺序标记每个页面,并在页面中显示键/指针。因此,包含键值k1和k2的页面P将为P:[k1,k2]
。
现在密钥3出现了。根据第5.2.1节...插入,第一个任务是搜索。这确定键3应该在页面A上-这是我们唯一的页面。进一步说“如果[那个节点]已满,它将被分为两个节点。” 页面已满,因此必须拆分。现在我们有
A:[1,2] B:[3, ]
但这不是一棵树!正如书中所说:
将指向[新节点] ..的指针插入[当前节点] 的父节点..中,在该节点[即父节点]中重复插入操作。如有必要,此拆分和上移过程可以继续进行,如果必须拆分,则将创建一个新的根节点。
(我强调显示处理过程是沿着树向根部向上延伸,而不是朝叶向下延伸。)
因此,我们必须将指向新页面(B)的指针放在当前页面(A)的父亲中。必须有一个新的根节点:
C:[2,3]
/ \
A:[1,2] B:[3, ]
我在非叶子页面中的指针指向子(儿子)节点中的最大值。您链接的文本可能会有所不同,但是结果是相同的。
键值4到达;根据算法,我们搜索以找到应该在哪个页面上。它应该在页面B上。它有空间,因此我们更新该页面和页面C上的指针:
C:[2,4]
/ \
A:[1,2] B:[3,4]
接下来,我们插入密钥5。它应该进入B页,但已满。因此它分裂
C:[2,4]
/ \
A:[1,2] B:[3,4] D:[5, ]
我们必须更新父节点。它也已满,因此会拆分:
C:[2,4] E:[5, ]
/ \ \
A:[1,2] B:[3,4] D:[5, ]
拆分传播并形成新的根节点:
F:[4,5]
/ \
C:[2,4] E:[5, ]
/ \ \
A:[1,2] B:[3,4] D:[5, ]
通过向上生长,树在每个分支中保持相同的深度。这对于可预测的性能很重要。(出于这个原因,有人说B树中的B代表“平衡”。)
至于第二部分-“是否可以以不同的顺序使用键输入记录以使树的高度减小?” 每个节点有5个键和两个键,我们至少需要3个叶节点来保存所有值,并需要3个高度来形成树。因此,对于给定的数据,序列和算法,我的安排是最佳的。
本书使用了与我使用的完全不同的指针排列方式,并使用了不同的页面拆分方式。这将是重要的,从而导致部分页面完整。在第42页上有一个名为“数据加载”的部分,它显示了如何通过加载键序列以外的内容来实现更完整的页面,这是我的直觉。但是,希望我给了您足够的指针,并且您将能够使用本书的指针结构自己解决问题。
我遇到了有关B树生长方式的交互式模拟。