【发布时间】:2015-07-26 16:07:11
【问题描述】:
我有一个 AVL 树,我想在其中返回 O(1) 中的中值元素。
我知道每次插入新元素时都可以保存指向它的指针,而无需更改插入的运行时间(通过保存子树的大小并遍历直到找到第 n/2 个大小的子树)。
但是我想知道我是否可以使用以下事实来做到这一点:在每次插入中,中位数都会“向右”移动,而在每次删除中,中位数都会“向左”移动。
以更一般的方式:如何使用前任和后继跟踪 AVL 树中的第 i 个元素?
【问题讨论】:
我有一个 AVL 树,我想在其中返回 O(1) 中的中值元素。
我知道每次插入新元素时都可以保存指向它的指针,而无需更改插入的运行时间(通过保存子树的大小并遍历直到找到第 n/2 个大小的子树)。
但是我想知道我是否可以使用以下事实来做到这一点:在每次插入中,中位数都会“向右”移动,而在每次删除中,中位数都会“向左”移动。
以更一般的方式:如何使用前任和后继跟踪 AVL 树中的第 i 个元素?
【问题讨论】:
给定一个 AVL(自平衡二叉搜索树),求中位数。请记住,即使树是平衡的,您也不能只取根元素,因为即使树是平衡的,您也不知道中位数是否恰好是左子或右子的根元素。用于查找 AVL 中位数的迭代算法。该算法基于每个 AVL 树的属性,您可以使用中序遍历获得包含该树元素的排序集合。使用此属性,我们可以获得已排序的节点集合,然后找到中位数。该算法的复杂度在时间和空间上为 O(N),其中 N 是树中的节点数。
public class AvlTreeMedian {
BinaryTreeInOrder binaryTreeInOrder;
public AvlTreeMedian() {
this.binaryTreeInOrder = new BinaryTreeInOrder();
}
public double find(BinaryNode<Integer> root) {
if (root == null) {
throw new IllegalArgumentException("You can't pass a null binary tree to this method.");
}
List<BinaryNode<Integer>> sortedElements = binaryTreeInOrder.getIterative(root);
double median = 0;
if (sortedElements.size() % 2 == 0) {
median = (sortedElements.get(sortedElements.size() / 2).getData() + sortedElements.get(
sortedElements.size() / 2 - 1).getData()) / 2;
} else {
median = sortedElements.get(sortedElements.size() / 2).getData();
}
return median;
}
}
【讨论】: