【发布时间】:2013-02-26 14:50:19
【问题描述】:
假设我有一个平衡的二叉搜索树来表示这个有序序列。
A<B<C<D<E<F<G<H
给定其中一个元素,例如 F,我如何有效地转换树以使结果代表这个有序序列?
F<G<H<A<B<C<D<E?
从 F 向右的元素被移动到所有其他元素的前面。请注意,这与通常意义上的“树旋转”无关。这里的旋转发生在元素顺序的意义上。这与双向链表的“旋转”的含义相同。例如,如果问题是关于双向链表而不是二叉搜索树,则解决方案很简单:
E.next := null
F.prev := null
H.next := A
A.prev := H
平衡二叉搜索树是否有有效的解决方案?
实施说明:
乍一看,即使有一个有效的算法,它似乎也没有多大用处,因为必须更新移动元素的值以保留二叉搜索树的不变量(左孩子更小,右孩子更大)。然而,情况并非如此,因为在模算术模N中,可以在恒定时间内固定顺序而不改变节点的值。假设节点的顺序定义如下:
(A < B) if and only if ((A.value - C) mod N) < ((B.value - C) mod N)
这里,A.value、B.value和C是[0,N)范围内的整数时间>。对此的图形解释是,我们有一个散布有 N 个点的圆,我们对这些点进行排序,使得 C 是最少的点,然后是 C +1、C+2等,直到C+(N-1),这是最大的点。
无论如何,在将 F 和所有后续元素移到前面后,可以通过更改 C 轻松修复树不变量:
C := F.value
【问题讨论】:
-
请定义“高效”。您可以在 O(N) 中重建整棵树。这够好吗?如果没有,你真的需要改变树吗?指向“第一个”元素的指针不好吗?
-
还取决于树的平衡方式,即它是伸展树还是红黑树,或者它是否由于其他原因恰好以当前形式平衡。
-
@comocomocomocomo 高效意味着 log(n)。您关于保留第一个元素指针的想法应该可行。要按顺序迭代树,您将从“第一个”元素开始,在末尾环绕,并在再次遇到“第一个”元素之前结束。你应该发布一个答案:)
-
@antti.huima 这是一棵 AVL 树,但我希望该解决方案适用于各种平衡树。
-
@AmbrozBizjak:我会的:-)
标签: algorithm rotation binary-search-tree