Arrays 我可以使用Day Stout Warren重新平衡数组中实现的二叉搜索树吗?

Arrays 我可以使用Day Stout Warren重新平衡数组中实现的二叉搜索树吗?,arrays,algorithm,tree,Arrays,Algorithm,Tree,因此,我实现了一个由数组支持的二叉搜索树。全面实施是必要的 因为树由数组支持,所以我通过对当前索引执行算术来确定左和右子级 private Integer getLeftIdx(Integer rootIndex) { return 2 * rootIndex + 1; } private Integer getRightIdx(Integer rootIndex) { return 2 * rootIndex + 2; } 我已经意识到,当树变得不平衡时,这会变得非常低效,

因此,我实现了一个由数组支持的二叉搜索树。全面实施是必要的

因为树由数组支持,所以我通过对当前索引执行算术来确定左和右子级

private Integer getLeftIdx(Integer rootIndex) {
    return 2 * rootIndex + 1;
}

private Integer getRightIdx(Integer rootIndex) {
    return 2 * rootIndex + 2;
}
我已经意识到,当树变得不平衡时,这会变得非常低效,部分原因是数组将被稀疏填充,部分原因是树的高度将增加,导致搜索趋向于O(n)

我正在寻找重新平衡树的方法,但我不断遇到这样的算法,它们似乎依赖于树的链表实现


这只是阵列实现的折衷吗?我似乎想不出一种不创建第二个数组就可以重新平衡的方法

假设您有一个长度为M的数组,其中在不同位置包含N个项目(当然,N 要做到这一点,您可以先从头到尾遍历数组,将所有项目打包在一起,然后从头到尾遍历数组,将项目移动到找到的每个有效位置,直到项目用完为止

这个简单的问题与您的问题相同,只是您不希望以“索引顺序”遍历数组,而是希望以二进制顺序遍历数组

您希望将所有项移动到“有效位置”,即数组中与索引 因此,以相反的顺序遍历数组,按最后可能的位置将项目打包到顺序中。然后按顺序向前浏览项目,将每个项目放入顺序第一个可用的有效位置有效位置,直到项目用完

但是注意:这是很有趣的,但是它不会让你的树对插入很有效率——你必须做太多的重新平衡来保持数组的合理大小。 但请注意:您实际上不必重新平衡整个树。当插入没有空闲位置时,只需重新平衡路径上具有额外空间的最小子树。我模模糊糊地记得我认为适用的一个结果,它表明当数组具有固定数量的额外级别时,使用此方法插入的摊销成本为O(log^2 N)。当我有时间的时候,我会计算出真正的成本

我经常遇到像Day Stout Warren这样的算法,它们似乎依赖于树的链表实现

这是不完全正确的。本文讨论了树嵌入到数组中的情况。事实上,第3节专门讨论了必要的修改。它展示了如何使用恒定的辅助空间来实现这一点

但是请注意,它们的实现与您的实现之间存在差异

您的想法是使用二进制堆顺序,一旦知道单个数字索引i,就可以确定子级(或父级)的索引。通常,数组不是按递增索引排序的


本文的思想是使用一个按递增索引排序的数组,并在重新平衡时将元素压缩到数组的开头。使用此实现,您不会通过索引i指定元素。相反,在二进制搜索中,您可以通过一对(b,e)间接指定一个元素,其思想是将索引隐式指定为⌊(b+e)/2⌋, 但是这些信息可以让你决定如何向左或向右走

感谢您参考原始论文——这是一个很好的提醒,作为一名维基百科学者,你只能走这么远。微妙但重要的一点。谢谢像红黑这样的自平衡树会有帮助吗?@VishalKotcherlakota不会。红黑树的平衡度不足以使阵列中的存储变得高效。此外,在链接树中快速(恒定时间)的重新平衡操作在树数组中非常缓慢(线性时间)。