繁体   English   中英

找到B +树的中位数

[英]Finding the median in B+ tree

我需要实现一个B +树。

我需要创建以下方法:

  1. 插入(x) - 0(log_t(x))。
  2. 搜索 - 成功搜索 - O(log_t(x))。 不成功的搜索 - O(1){有很高的可能性}

所以我开始实现Insert(x) - 每次我有一个完整的叶子,我想把它分成两个分开的叶子。 一个键的键等于或低于中值键,第二个键将包含值高于中值的键。

如何在不损害运行时间的情况下找到此中位数?

我想过:

  1. 将每个内部节点和叶子表示为较小的B +树,但只有当树完全平衡时,中位数才是根(或根中的一个元素)。
  2. 将每个内部节点和叶子表示为双向链表。 并且在插入输入时尝试获取中值键,但是输入不适用于它。
  3. 表示为数组可能会给我中间,但是当我将其拆分时,我需要至少O(n / 2)将键插入到新数组中。

我能做什么?

关于搜索,想法明智:成功和不成功搜索之间的区别在于在叶子中搜索,但我仍然需要通过树的不同键“运行”以确定密钥是否在树中。 那怎么可能是O(1)?

在B +树中,所有值都存储在叶子中。

请注意,您可以将每个叶子的指针添加到下一个叶子,除了标准B +树之外,您还可以获得包含所有元素有序链接列表

现在,请注意,假设您知道此链接列表中的当前中位数是什么 - 在插入/删除时,您可以便宜地计算新的中位数 (它可以是相同的节点,下一个节点或前一个节点,没有其他选择)。
请注意,修改此指针是O(1) (尽管插入/删除本身是O(logn)

鉴于这些知识 - 可以缓存指向中值元素的指针,并确保在删除/插入时保留它。 当你要求中位数时 - 只需从缓存中取中位数 - O(1)


关于Unsuccessful search - O(1) {With a high likely-hood} - 这个是尖叫blo bloom过滤器 ,这是一个概率集实现,从来没有假阴性(从来没有说过某些东西没有设置),但是一些误报(说某些东西在缓存中,而事实上并非如此)。

你不需要B + -tree的中位数。 您需要在要拆分的节点中使用中值键。 您必须在该中位数处进行拆分以满足每个节点具有N / 2 <= n <= N个键的条件。 节点中的中间密钥只是中间的密钥, n / 2 ,其中n是节点中实际密钥的数量。 这就是你拆分节点的地方。 计算是O(1):它不会伤害运行时。

在不叠加其他数据结构的情况下,您无法从B +树获得O(1)搜索失败时间。

我已经发布了一个答案(并且已经删除了),但我可能会误解,所以这里有另一种解释的答案......

如果您需要始终知道哪个项目是完整 B +树容器中的中位数,该怎么办?

正如amit所说,你可以将指针(以及你的根指针)保存到包含中位数的当前叶节点。 您还可以在该叶节点中保留索引。 因此,您可以通过直接跟踪到正确的节点和项目来获得O(1)访问权限。

问题在于维持这一点。 当然amit是正确的,对于每个插入,中位数也必须保持相同的项目,或者必须步骤到之前或之后的那个。 如果您通过叶节点有一个链表,即使这意味着步进到相邻的叶节点,也可以有效地处理。

但是,我不相信,确定是否或采用哪种方式都是微不足道的,除非在中位数和插入恰好位于同一叶节点的特殊情况下。

如果您知道完整树的大小(可以使用根指针轻松存储和维护),则至少可以确定插入前后中间项应该在哪个索引处。

但是,如果插入点位于中位数之前或之后,您需要知道先前的中位数项是否已将其指数向上移动。 除非插入点和中位数碰巧在同一节点中,否则这是一个问题。

Overkill方式 - 扩充B +树以支持计算项目的索引并搜索索引。 其诀窍是每个节点保留其子树的叶节点中的项目总数。 这可以推高一个级别,因此每个分支节点都有一个子树大小数组及其子节点指针数组。

这提供了两种解决方案 您可以使用该信息在搜索时确定插入点的索引,或者(提供节点具有父指针)您可以使用它来重新确定插入后的上一个中间项的索引。

[实际上是三个。 插入后,你可以根据新的大小搜索新的中途索引而不参考前面的中间链接。]

然而,就存储用于增强的数据而言,这结果是过度的。 您不需要知道插入点的索引或先前的中位数 - 您可以知道插入的中位数的哪一侧。 如果您知道要从根到中间项的跟踪,您应该能够在搜索插入点时跟踪它的哪一侧。 因此,您只需要增加足够的信息来查找和维护该踪迹。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM