【问题标题】:Optimizing AVLTree with B-tree用 B-tree 优化 AVLTree
【发布时间】:2021-05-24 02:38:16
【问题描述】:

前提

所以最近我一直在思考一个数据库常见的问题:尝试优化数据的插入、搜索、删除和更新。 通常我看到现在大多数数据库都使用 BTree 或 B+Tree 来解决这样的问题,但它们通常用于将数据存储在磁盘内,我想处理内存中的数据,所以我考虑使用AVLTree(差异应该很小,因为 BTrees 的目的与 AVLTree 相同,但实现不同,效果也不同)。 在继续这背后的推理之前,我想更深入地了解我想要解决的问题。 因此,在现代数据库中,存储在带有 PRIMARY KEY 的表中的数据往往是 INDEXED (我在索引方面不是很有经验,所以我要说的是我对这个问题的基本推理),通常 PRIMARY KEY 是一个越来越多的数字(即使现在是一种不好的做法)从 1 开始。 通常使用 AVLTree 应该足以解决问题,因为这棵特定的树总是平衡的并提供 O(log2(n)) 操作,但我想在更深层次上达到这一点,试图对其进行更多的优化。

理论

因此,正如问题的标题所示,我正在尝试优化 AVLTree,将其与 Btree 合并。 基本上,这棵新树的每个节点都可以说是一个由十个元素组成的数组,每个节点也是树中相应的高度,并且数组的每个元素都是按升序排列的。

插入

插入最初填充根节点的数组,当根节点已满时,它会生成左右子节点,其中也包含 10 个元素的数组。 每当添加新节点时,树都会根据左右子节点向量的第一个键使用它们的高度自动重新平衡节点(请注意,这实际上是 AVLTree 的行为方式,但 AVLTree 只有 2 个节点,没有向量而已值)。

搜索

搜索元素是这样工作的:从根开始,我们将搜索的值K与当前节点数组的第一个和最后一个键进行比较,如果值介于两者之间,我们知道它肯定会位于当前节点的数组中,因此我们可以开始使用复杂度为 O(log2(n)) 的 binarySearch 进入这个由十个元素组成的数组,否则如果我们搜索的键小于第一个键或如果它更大,我们就往右边走。

删除

与搜索相同,但我们删除了该值。

更新

与搜索相同,但我们更新了值。

结论

如果我没记错的话,这应该有 O(log10(log2(10))) 的复杂度,它总是对数的,所以我们不应该关心这个优化,但在我看来,这可能会使树的高度如此之小,同时也提供了快速的搜索时间。

【问题讨论】:

  • 不,一个操作的复杂度是O(log10(n)+log2(10)) = O(logn)。它与 AVL 或 B-tree 没有什么不同。
  • 您在最后一段中的编辑使时间复杂度的错误更加严重。请保持原样,因为我已经发布了关于此的答案。
  • 我同意你所说的,但在撰写本文时我认为 O(log10(log2(10)) 是正确答案,我在写作时犯了一个错误,所以如果我必须错了,至少我想保持一致。

标签: database optimization tree time-complexity binary-search


【解决方案1】:

B树和B+树确实是因为块的设计而用于磁盘存储的。但是没有理由不能将它们也用作内存数据结构。

B 树的优点包括它在单个节点内使用数组。在可能有 10 个条目的有限向量中查找可能非常快。

您在 B 树和 AVL 之间折衷的想法肯定会奏效,但请注意:

  • 您需要像在 AVL 中一样执行树旋转以保持树平衡。在 B 树中,您使用重新分配、合并和拆分,但没有旋转。
  • 与 AVL 一样,树并不总是完美平衡的。
  • 您需要描述当向量已满且需要向其添加值时将执行的操作:节点必须拆分,一半必须作为叶子重新注入。
  • 您需要描述当向量获得非常低的填充因子(由于删除)时将执行的操作。如果你这样离开它,树可能会退化成一个 AVL 树,其中每个向量只有 1 个值,然后额外的向量开销将使其效率低于真正的 AVL 树。要使向量的填充因子保持在最小值以上,您不能像在 B 树中那样轻松地对兄弟节点应用重新分配机制。它适用于叶节点,但不适用于内部节点。所以这需要澄清...
  • 您需要描述更新向量中的值时将执行的操作。当然,您可以将它插入到它的排序位置:但是如果它成为该向量中的第一个或最后一个值,这可能会违反左右孩子的顺序,因此您可能还需要更精确地定义算法。
  • 在 10 的向量中进行二分搜索可能有点过头了:简单的从左到右扫描可能会更快,因为 CPU 已针对读取连续内存进行了优化。这不会影响时间复杂度,因为我们将向量大小限制为 10。所以我们谈论的是最多进行 4 次比较(平均 3-4 次,具体取决于二进制搜索实现)或最多 10 次比较(5平均)。

如果我没记错的话,它的复杂度应该是 O(log10(log2(n))),它总是对数的

实际上,如果这是真的,那将是次对数,即 O(loglogn)。但是这里有一个错误。向量中的二分查找与 n 无关,而是与 10 相关。此外,这项工作还包含 addition 以查找具有该向量的节点。所以它不是对数的对数,而是对数的和:

O(log10n + log210) = O(log n)

因此,时间复杂度与 AVL 或 B-tree 的时间复杂度没有什么不同——前提是算法完成时缺少细节,保持在对数复杂度内。

您也许还应该考虑实现纯 B 树或 B+ 树:这样您还可以从 AVL 和中间结构都没有的一些优点中受益:

  • 树的叶子都在同一层次
  • 无需旋转
  • 树的高度只在一个地方发生变化:根。
  • B+ 树为按顺序迭代所有值提供了一种非常快速的方法。

【讨论】:

    猜你喜欢
    • 2017-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-24
    • 1970-01-01
    • 2015-04-17
    • 1970-01-01
    • 2021-10-30
    相关资源
    最近更新 更多