计算AVL树

时间:2015-08-30 15:34:23

标签: java algorithm tree avl-tree

假设我有一个不同整数的AVL树。我需要确定位于区间[a,b)中的节点数量,其中a<湾注意,[a,b)由用户提供,因此我事先不知道a和b的值是什么。此外,a和b可能根本不存在于树中。例如,如果我有一个包含整数{1,2,4,5,6,7}的树,那么如果用户提供间隔[3,7],则用户应该期望得到3。

一个简单的实现是遍历每个节点,并在每次在给定间隔中找到节点时将计数增加1。但是这将具有O(n)的最坏情况时间复杂度,因为树中的每个单个整数都可能在给定范围内。我需要一个更快的算法,并且在做了一些研究之后我发现它需要在每个节点中存储大小统计量,以便可以容易地计算任何给定节点的秩。

我想做排名(b) - 排名(a),但问题是a和b可能不存在于树中。在上面的例子中,rank(7)将返回6,但rank(3)将不返回任何有意义的值。

有人可以就如何解决这个问题提出建议吗?另外,我知道在这个网站上还有另一个类似的问题,但是这个问题涉及C ++,而这个问题涉及Java。而且,我在那里找不到满意的答案。

2 个答案:

答案 0 :(得分:0)

而不是

rank(b) - rank(a)

我会做的是

rank(X) - rank(Y)

X是第一个具有值>的节点。湾

Y是第一个具有值> = a。

的节点

答案 1 :(得分:0)

我在很久以前为AVL树实现了一个基于堆栈的树迭代器。它应该适用于你的情况:

  • 创建一个数组“treestack”,它包含遍历信息的结构。结构只需要一个bool“visited”,以及一个指向你的节点类型的指针。该阵列可以是静态大小,例如保持64个信息元素(每个树级一个,所以这64个意味着你的树包含最多4G节点)
  • 当您开始搜索时,更改AVL树的搜索方法以将根节点放在treestack [0]上,并在搜索期间跟随左右子节点时将所有其他节点放在treestack之上。编辑:请注意,不成功的搜索将导致您的treestack具有下一个较小或下一个更高值的节点,这正是您想要的(只是在它更小的情况下跳过计数,我们仍然具有无效的迭代器启动誓言)。

您现在已经是一个路径,而不是您的treestack,您可以将其用于后续的有序遍历,以查找下一个更高的值。使用堆栈的顺序遍历如下:

  • 从treestack中的最后一个元素开始,保留一个treeindex,它最初是=最后一项的arrayindex。
  • 如果有一个正确的节点,并且未标记为已访问:请尝试按照当前节点的一个右侧,然后ENDLESS到任何后续节点的左侧。无论你停在哪里(如果没有左边的节点,只有一个右边的节点)也是下一个更高的值。将所有节点放在树堆的末尾,并按照它们的顺序放置树形索引。并选择具有下一个更高值的选择的最终节点作为访问。增加节点计数器+ 1。
  • 现在要查找后续更高的值,通过将treestack中的treeindex-1作为当前节点在树中提升,重复上述步骤以查找具有更高值的下一个节点。
  • 如果当前节点没有右子节点,并且节点未标记为visited:标记为已访问,而inc节点计数器为1
  • 当您使用treeindex 0或包含最大值的节点到达根节点时,您已完成。

我希望它有所帮助。