通常,基于二叉树的抽象可以使用实际链接节点对象或数组来实现,其中每个节点都有指向其两个子节点的指针。在索引为k的节点中,其子节点为2k和2k+1。
除了节点占用少量额外内存之外,总体复杂度似乎是相同的。
它们之间是否存在具体优势?据我所见,二叉堆倾向于使用数组实现,而二叉搜索树倾向于使用链接节点实现。这样做的原因是什么呢?
通常,基于二叉树的抽象可以使用实际链接节点对象或数组来实现,其中每个节点都有指向其两个子节点的指针。在索引为k的节点中,其子节点为2k和2k+1。
除了节点占用少量额外内存之外,总体复杂度似乎是相同的。
它们之间是否存在具体优势?据我所见,二叉堆倾向于使用数组实现,而二叉搜索树倾向于使用链接节点实现。这样做的原因是什么呢?
数组不能有效地表示任意形状的二叉树,只能表示 完全 二叉树。 完全二叉树是指所有层都是满的,或者除最深层外的所有层都是满的,最深层的节点尽可能靠左。 (您可以想象每一层从左到右填充节点,并且必须在下一层开始之前填满一层。)
堆是完全二叉树,因此使用数组实现由于其卓越的内存效率。 另一方面,必须支持在任意位置插入和删除的二叉搜索树(因此可能不是完全二叉树)无法使用数组实现。
Node
:它要么是Filled
,包含键和辅助数据,要么是类似于Nil
(也称为空指针)的Empty
。如果您需要支持的唯一操作是delete
,那么您已经准备好了:只需实现build
操作以返回完整的树,然后实现正常的二叉树delete
操作即可。不需要平衡来实现O(log n)
复杂度界限(其中n
是树中初始项的数量)。insert
操作。简单地说,您维护一个近乎完整的树,存储大小不超过2n
(其中n
是树中当前项目数)。插入新项目时,您检查要插入的适当数组单元格的位置:如果它在分配的存储内部,则只需将其写入该单元格。否则,您从该单元格的父项开始向上遍历树,直到找到一个子树,其存储具有足够的空间来容纳所有项目,包括新项目;如果不存在这样的子树,则将存储器加倍。找到该子树后,将其重建为近乎完整的形状,并将新项目插入正确的数组单元格(现在保证在分配的存储内)。所有这些都可以在摊销的O(log^2(n))
时间内完成,或者通过更多的努力在摊销的O(log(n))
时间内完成。build
、delete
、delete_range
、query_range
和iter
操作,并在insert
分支上进行了实验性的insert
操作。该项目页面还包含一些基准测试,显示该数据结构至少对某些用途是可行的。
nil
。 - Tilak Madichetti